首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL Server 交易 (Transaction) 核心概念、ACID 特性與實戰範本

     編輯:關於SqlServer

什麼是交易?

交易 是一組不可分割的工作邏輯單元,包含一或多個 T-SQL 陳述式。這些陳述式要么**全部成功認可**,要么**全部失敗回滾**,資料庫永不會停留在中間狀態。

交易的三種啟動模式

模式說明適用場景
自動認可 (預設)每條陳述式隱含交易,成功自動 COMMIT,失敗自動 ROLLBACK單一陳述式操作
顯式交易開發者以 BEGIN TRAN 明確啟動,COMMIT/ROLLBACK 明確結束多步驟業務邏輯、需原子性
隱含交易SET IMPLICIT_TRANSACTIONS ON 後,首條 DML 自動啟動交易,需顯式 COMMIT/ROLLBACK舊版移植、特定框架需求

交易控制陳述式

BEGIN TRAN[SACTION] [tran_name | @tran_var]  -- 啟動交易,可命名
COMMIT TRAN[SACTION] [tran_name | @tran_var] -- 認可交易
ROLLBACK TRAN[SACTION] [tran_name | @tran_var | savepoint_name] -- 回滾 (可到儲存點)
SAVE TRAN[SACTION] savepoint_name           -- 設定儲存點 (部分回滾用)
@@TRANCOUNT                                 -- 目前交易巢狀層級 (每 BEGIN +1, COMMIT -1, ROLLBACK 歸零)

ACID 四大特性深度解析

  1. 原子性:交易內所有操作視為不可分割整體,全做或全不做。
  2. 一致性:交易完成前後,資料庫從一個一致性狀態轉移到另一個一致性狀態 (所有約束、觸發器、規則均滿足)。
  3. 隔離性:並發交易間互不干擾,透過鎖定、資料列版本控制實現。隔離等級決定可見度。
  4. 持久性:交易一旦 COMMIT,其變更永久寫入交易記錄檔與資料檔,即便系統崩潰也不會遺失。

隔離等級與並發現象

隔離等級髒讀不可重複讀虛讀備註
READ UNCOMMITTED✅ 可能✅ 可能✅ 可能效能最好,極少用
READ COMMITTED (預設)❌✅ 可能✅ 可能平衡點,依賴共享鎖
REPEATABLE READ❌❌✅ 可能保持共享鎖至交易結束
SNAPSHOT❌❌❌資料列版本控制,需啟用 DB 選項
SERIALIZABLE❌❌❌範圍鎖,並發度最低

設定方式:SET TRANSACTION ISOLATION LEVEL READ COMMITTED; (僅影響目前工作階段後續交易)

實戰範本:錯誤累計與條件認可/回滾

CREATE PROCEDURE usp_UpdateOfficeRent
    @OfficeID INT,
    @NewHits INT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @ErrorSum INT = 0;

    BEGIN TRANSACTION; -- 顯式啟動

    -- 步驟 1:更新建立時間
    UPDATE dbo.OfficeRent SET CreateTime = GETDATE() WHERE OfficeID = @OfficeID;
    SET @ErrorSum += @@ERROR; -- 累計錯誤碼 (0=成功)

    -- 步驟 2:更新點擊數
    UPDATE dbo.OfficeRent SET Hits = @NewHits WHERE OfficeID = @OfficeID;
    SET @ErrorSum += @@ERROR;

    -- 判斷並處理
    IF @ErrorSum <> 0
    BEGIN
        PRINT N'發生錯誤,執行回滾';
        ROLLBACK TRANSACTION;
    END
    ELSE
    BEGIN
        PRINT N'全部成功,提交交易';
        COMMIT TRANSACTION;
    END
END

現代最佳實務:TRY...CATCH + XACT_STATE

CREATE PROCEDURE usp_ModernTransaction
    @Param INT
AS
BEGIN
    SET NOCOUNT ON;
    BEGIN TRY
        BEGIN TRANSACTION;
            -- 核心業務邏輯
            UPDATE Table1 SET Col1 = @Param WHERE ID = 1;
            INSERT INTO Table2 (ColA) VALUES (@Param);
            -- 故意製造錯誤測試
            -- SELECT 1/0;
        COMMIT TRANSACTION;
    END TRY
    BEGIN CATCH
        -- XACT_STATE() = 1 可認可, -1 必須回滾, 0 無交易
        IF XACT_STATE() = -1
            ROLLBACK TRANSACTION;
        ELSE IF XACT_STATE() = 1
            COMMIT TRANSACTION; -- 視業務決定是否部分認可

        -- 記錄錯誤至日誌表
        INSERT INTO ErrorLog (ProcName, ErrorNumber, ErrorMessage, ErrorTime)
        VALUES (OBJECT_NAME(@@PROCID), ERROR_NUMBER(), ERROR_MESSAGE(), SYSDATETIME());

        THROW; -- 向上拋出,讓呼叫端知曉
    END CATCH
END

不可包含在交易中的作業

以下 DDL/管理命令會隱含認可目前交易,無法回滾:

  • CREATE/ALTER/DROP DATABASE
  • BACKUP/RESTORE DATABASE/LOG
  • DISK INIT, RECONFIGURE
  • UPDATE STATISTICS
  • GRANT/REVOKE/DENY
  • sp_configure 後的 RECONFIGURE

巢狀交易陷阱

SQL Server 不支援真正的巢狀交易。BEGIN TRAN 只是遞增 @@TRANCOUNT,只有最外層的 COMMIT 才真正寫入磁碟;任一層 ROLLBACK 會將 @@TRANCOUNT 歸零並回滾全部。建議:

  • 在預存程序最外層控制交易。
  • 子程序若需交易語意,使用 SAVE TRANSACTION 做部分回滾,或檢查 @@TRANCOUNT > 0 決定是否自行啟動。

總結

掌握 顯式交易、ACID、隔離等級、TRY...CATCH + XACT_STATE 現代模式,即能撰寫健壯、高並發的資料庫業務邏輯。記住:交易要短、要快、鎖定資源要少,是高效能系統的鐵律。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved