事務的嵌套

在SqlServer裏,嵌套事務的層次是由@@TranCount全局變量反映出來的。每一次Begin Transaction都會引起@@TranCount加1。而每一次Commit Transaction都會使@@TranCount減1,而RollBack Transaction會回滾所有的嵌套事務包括已經提交的事務和未提交的事務,而使@@TranCount置0。例如:
Begin Transaction -- @@TranCount = 1
BeginTransaction -- @@TranCount = 2 
BeginTransaction -- @@TranCount = 3
Commit Transaction -- @@TranCount = 2
Commit Transaction -- @@TranCount = 1
Commit Transaction -- @@TranCount = 0
如果出現錯誤ROLLBACK TRANSACTION 
則:
Begin Transaction -- @@TranCount = 1
BeginTransaction -- @@TranCount = 2 
BeginTransaction -- @@TranCount = 3
ROLLBACK TRANSACTION -- @@TranCount = 0
Commit Transaction -- @@TranCount = 0---出現錯誤
Transaction count after EXECUTE indicates that a COMMIT or ROLLBACK TRANSACTION statement is missing. Previous count = 1, current count = 0.
如果被嵌套的事務中發生錯誤,最簡單的方法應該是無論如何都先將它提交,同時返回錯誤碼(一個正常情況不可能出現的代碼 如 -1)讓上一層事務來處理這個錯誤,從而使@@TranCount 減1。 這樣外層事務在回滾或者提交的時候能夠保證外層事務在開始的時候和結束的時候保持一致。由於裏層事務返回了錯誤碼,因此外層事務(最外層)可以回滾事務,這樣裏面已經提交的事務也可以被回滾而不會出現錯誤。
在項目中應該會常常出現這樣的情況,一個存儲過程裏面用了事務,但是不能保證它會被別的帶有事務的存儲過程調用,如果單獨調用的話,出現錯誤可以直接回滾,但是如果是被別的帶事務的存儲過程調用的話,RollBack 就會出錯了。因此需要一種機制來區分,建立一個臨時的變量來區分是否嵌套,和嵌套的層數,如下:

DECLARE @TranCounter INT;
SET @TranCounter = @@TRANCOUNT;
IF @TranCounter > 0
SAVE TRANSACTION ProcedureSave;
ELSE
BEGIN TRANSACTION;
…………
--事務內要執行的代碼
…………

IF @@ERROR<>0
goto Error
 Commit Transaction
Commit Transaction
--下面返回要返回的值0只是個例子
Return 0
Error:
IF @TranCounter = 0
ROLLBACK TRANSACTION;
Else 
ROLLBACK TRANSACTION ProcedureSave;

Return @Error
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章