事務操做(BEGIN/COMMIT/ROLLBACK/SAVE TRANSACTION)

BEGIN TRANSACTION

標記一個顯式本地事務的起始點。 BEGIN TRANSACTION 使 @@TRANCOUNT 按 1 遞增。程序員

BEGIN TRANSACTION 表明一點,由鏈接引用的數據在該點邏輯和物理上都一致的。 若是趕上錯誤,在 BEGIN TRANSACTION 以後的全部數據改動都能進行回滾,以將數據返回到已知的一致狀態。 每一個事務繼續執行直到它無誤地完成而且用 COMMIT TRANSACTION 對數據庫做永久的改動,或者趕上錯誤而且用 ROLLBACK TRANSACTION 語句擦除全部改動。數據庫

BEGIN TRANSACTION 爲發出本語句的鏈接啓動一個本地事務。 根據當前事務隔離級別的設置,爲支持該鏈接所發出的 Transact-SQL 語句而獲取的許多資源被該事務鎖定,直到使用 COMMIT TRANSACTION 或 ROLLBACK TRANSACTION 語句完成該事務爲止。 長時間處於未完成狀態的事務會阻止其餘用戶訪問這些鎖定的資源,也會阻止日誌截斷。服務器

雖然 BEGIN TRANSACTION 啓動一個本地事務,可是在應用程序接下來執行一個必須記錄的操做(如執行 INSERT、UPDATE 或 DELETE 語句)以前,它並不被記錄在事務日誌中。 應用程序能執行一些操做,例如爲了保護 SELECT 語句的事務隔離級別而獲取鎖,可是直到應用程序執行一個修改操做後日志中才有記錄。分佈式

語法函數

BEGIN { TRAN | TRANSACTION }spa

    [ { transaction_name | @tran_name_variable }日誌

      [ WITH MARK [ 'description' ] ]code

    ]blog

[ ; ]事務

參數

transaction_name

分配給事務的名稱。 transaction_name 必須符合標識符規則,但標識符所包含的字符數不能大於 32。 僅在最外面的 BEGIN...COMMIT 或 BEGIN...ROLLBACK 嵌套語句對中使用事務名。 transaction_name 始終是區分大小寫的,即便 SQL Server 實例不區分大小寫也是如此。

@tran_name_variable

用戶定義的、含有有效事務名稱的變量的名稱。 必須用 char、varchar、nchar 或 nvarchar 數據類型聲明變量。 若是傳遞給該變量的字符多於 32 個,則僅使用前面的 32 個字符;其他的字符將被截斷。

WITH MARK [ 'description' ]

指定在日誌中標記事務。 description 是描述該標記的字符串。 長於 128 個字符的 description 先截斷爲 128 個字符,而後才存儲到 msdb.dbo.logmarkhistory 表中。

若是使用了 WITH MARK,則必須指定事務名。 WITH MARK 容許將事務日誌還原到命名標記。

COMMIT TRANSACTION

標誌一個成功的隱性事務或顯式事務的結束。僅當事務引用的全部數據在邏輯上都正確時,才應發出 COMMIT TRANSACTION 命令。 若是 @@TRANCOUNT 爲 1,COMMIT TRANSACTION 使得自從事務開始以來所執行的全部數據修改爲爲數據庫的永久部分,釋放事務所佔用的資源,並將 @@TRANCOUNT 減小到 0。若是 @@TRANCOUNT 大於 1,則 COMMIT TRANSACTION 使 @@TRANCOUNT 按 1 遞減而且事務將保持活動狀態。

若是所提交的事務是 Transact-SQL 分佈式事務,COMMIT TRANSACTION 將觸發 MS DTC 使用兩階段提交協議,以便提交全部涉及該事務的服務器。 若是本地事務跨越同一數據庫引擎實例上的兩個或多個數據庫,則該實例將使用內部的兩階段提交來提交全部涉及該事務的數據庫。當 @@TRANCOUNT 爲 0 時發出 COMMIT TRANSACTION 將會致使出現錯誤;由於沒有相應的 BEGIN TRANSACTION。

不能在發出一個 COMMIT TRANSACTION 語句以後回滾事務,由於數據修改已經成爲數據庫的一個永久部分。

僅當事務計數在語句開始處爲 0 時,數據庫引擎纔會增長語句內的事務計數。

語法

COMMIT [ { TRAN | TRANSACTION } [ transaction_name | @tran_name_variable ] ] [ WITH ( DELAYED_DURABILITY = { OFF | ON } ) ]

[ ; ]

參數

transaction_name

SQL Server 數據庫引擎忽略此參數。 transaction_name 指定由前面的 BEGIN TRANSACTION 分配的事務名稱。 transaction_name 必須符合標識符規則,但不能超過 32 個字符。 transaction_name 經過向程序員指明 COMMIT TRANSACTION 與哪些 BEGIN TRANSACTION 相關聯,可做爲幫助閱讀的一種方法。

@tran_name_variable

用戶定義的、含有有效事務名稱的變量的名稱。 必須用 char、varchar、nchar 或 nvarchar 數據類型聲明變量。 若是傳遞給該變量的字符數超過 32,則只使用 32 個字符,其他的字符將被截斷。

DELAYED_DURABILITY

請求將此事務與延遲持續性一塊兒提交的選項。 若是已用 DELAYED_DURABILITY = DISABLED 或DELAYED_DURABILITY = FORCED 更改了數據庫,則忽略該請求。

ROLLBACK TRANSACTION

將顯式事務或隱性事務回滾到事務的起點或事務內的某個保存點。 可使用 ROLLBACK TRANSACTION 清除自事務的起點或到某個保存點所作的全部數據修改。 它還釋放由事務控制的資源。ROLLBACK TRANSACTION 語句不生成顯示給用戶的消息。 若是在存儲過程或觸發器中須要警告,請使用 RAISERROR 或 PRINT 語句。 RAISERROR 是用於指出錯誤的首選語句。

語法

ROLLBACK { TRAN | TRANSACTION }

     [ transaction_name | @tran_name_variable

     | savepoint_name | @savepoint_variable ]

[ ; ]

參數

transaction_name

是爲 BEGIN TRANSACTION 上的事務分配的名稱。 transaction_name 必須符合標識符規則,但只使用事務名稱的前 32 個字符。 嵌套事務時,transaction_name 必須是最外面的 BEGIN TRANSACTION 語句中的名稱。 transaction_name 始終是區分大小寫的,即便 SQL Server 實例不區分大小寫也是如此。

@ tran_name_variable

用戶定義的、含有有效事務名稱的變量的名稱。 必須用 char、varchar、nchar 或 nvarchar 數據類型聲明變量。

savepoint_name

是 SAVE TRANSACTION 語句中的 savepoint_name。 savepoint_name 必須符合有關標識符的規則。 當條件回滾應隻影響事務的一部分時,可以使用 savepoint_name。

@ savepoint_variable

是用戶定義的、包含有效保存點名稱的變量的名稱。 必須用 char、varchar、nchar 或 nvarchar 數據類型聲明變量。

SAVE TRANSACTION

在事務內設置保存點。保存點能夠定義在按條件取消某個事務的一部分後,該事務能夠返回的一個位置。 若是將事務回滾到保存點,則根據須要必須完成其餘剩餘的 Transact-SQL 語句和 COMMIT TRANSACTION 語句,或者必須經過將事務回滾到起始點徹底取消事務。 若要取消整個事務,請使用 ROLLBACK TRANSACTION transaction_name 語句。 這將撤消事務的全部語句和過程。在事務中容許有重複的保存點名稱,但指定保存點名稱的 ROLLBACK TRANSACTION 語句只將事務回滾到使用該名稱的最近的 SAVE TRANSACTION。

語法

SAVE { TRAN | TRANSACTION } { savepoint_name | @savepoint_variable }

[ ; ]

參數

savepoint_name

分配給保存點的名稱。 保存點名稱必須符合標識符的規則,但長度不能超過 32 個字符。 transaction_name始終是區分大小寫的,即便 SQL Server 實例不區分大小寫也是如此。

@savepoint_variable

包含有效保存點名稱的用戶定義變量的名稱。 必須用 char、varchar、nchar 或 nvarchar 數據類型聲明變量。 若是長度超過 32 個字符,也能夠傳遞到變量,但只使用前 32 個字符。

示例

如下示例說明若是活動事務是在執行存儲過程以前啓動的,如何使用事務保存點僅回滾存儲過程所作的修改。

USE AdventureWorks2012;

GO

IF EXISTS (SELECT name FROM sys.objects

           WHERE name = N'SaveTranExample')

    DROP PROCEDURE SaveTranExample;

GO

CREATE PROCEDURE SaveTranExample

    @InputCandidateID INT

AS

   -- 檢查是不是在活動的事務裏面調用該存儲過程(嵌套事務)

   -- @TranCounter = 0 表示不是在活動事務裏面調用

   -- @TranCounter > 0表示在該存儲過程調用以前已經有一個活動的事務

    DECLARE @TranCounter INT;

    SET @TranCounter = @@TRANCOUNT;

    IF @TranCounter > 0

       -- 在該存儲過程調用以前已經有一個活動的事務。建立一個保存點,若是這個存儲過程出錯,只回滾到執行存儲過程以前的操做。

        SAVE TRANSACTION ProcedureSave;

    ELSE

        -- 建立一個新的事務

        BEGIN TRANSACTION;

    -- Modify database.

    BEGIN TRY

        DELETE HumanResources.JobCandidate

            WHERE JobCandidateID = @InputCandidateID;

.

        IF @TranCounter = 0

            -- @TranCounter = 0 只在這個存儲過程裏面有事務,必須提交事務

            COMMIT TRANSACTION;

    END TRY

    BEGIN CATCH

                                -- 錯誤發生,須要去判斷回滾級別

        IF @TranCounter = 0

            -- 事務只在此存儲過程當中,回滾整個事務

            -- Roll back complete transaction.

            ROLLBACK TRANSACTION;

        ELSE

            -- 事務在此存儲過程開始以前已經建立(嵌套事務)

              -- XACT_STATE(),用於報告當前正在運行的請求的用戶事務狀態的標量函數。 XACT_STATE 指示請求是否有活動的用戶事務,以及是否可以提交該事務。

              --  XACT_STATE() = 1 ,當前請求有活動的用戶事務。 請求能夠執行任何操做,包括寫入數據和提交事務。

              --  XACT_STATE() = 0,當前請求沒有活動的用戶事務。

              --  XACT_STATE() = -1 ,當前請求具備活動的用戶事務,但出現了導致事務被歸類爲沒法提交的事務的錯誤。 請求沒法提交事務或回滾到保存點;它只能請求徹底回滾事務。

              -- 請求在回滾事務以前沒法執行任何寫操做。 請求在回滾事務以前只能執行讀操做。 事務回滾以後,請求即可執行讀寫操做並可開始新的事務。

            IF XACT_STATE() <> -1

              -- 回滾到此存儲過程開始以前的錯做。

                ROLLBACK TRANSACTION ProcedureSave;

        -- 輸出錯誤信息

        DECLARE @ErrorMessage NVARCHAR(4000);

        DECLARE @ErrorSeverity INT;

        DECLARE @ErrorState INT;

        SELECT @ErrorMessage = ERROR_MESSAGE();

        SELECT @ErrorSeverity = ERROR_SEVERITY();

        SELECT @ErrorState = ERROR_STATE();

        RAISERROR (@ErrorMessage,

                   @ErrorSeverity,

                   @ErrorState

                   );

    END CATCH

GO
相關文章
相關標籤/搜索