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

SQL Server 2005 使用 TRY/CATCH 解決死鎖並實現自動重試

     編輯:關於SqlServer

死鎖示範:讀寫交叉阻塞

兩連線並行:
1. INSERT → WAITFOR DELAY '00:00:05' → SELECT ... LIKE 'Test%'
2. 同邏輯不同資料。
READ COMMITTED 隔離級下,SELECT 需共享鎖,遭對方 INSERT 排他鎖阻塞 → **互相等待 → 死鎖**。SQL Server 選犧牲者回滾,另一完成。

TRY/CATCH 捕獲死錯誤 (1205),避免批次中止

BEGIN TRANSACTION
BEGIN TRY
    INSERT Authors VALUES (@au_id, @au_lname, '', '', '', '', '', '11111', 0)
    WAITFOR DELAY '00:00:05'
    SELECT COUNT(*) FROM Authors
    COMMIT
END TRY
BEGIN CATCH
    SELECT ERROR_NUMBER() AS ErrorNumber  -- 1205
    ROLLBACK
END CATCH
SELECT @@TRANCOUNT  -- 0
  • TRY 區塊執行失敗 → 跳轉 CATCH。
  • 錯誤函數:ERROR_NUMBER(), ERROR_MESSAGE(), ERROR_SEVERITY(), ERROR_STATE(), ERROR_PROCEDURE() — 遠優於 @@ERROR。
  • **關鍵:** CATCH 內**必須顯式 ROLLBACK**,事務不會自動回滾。

進階:WHILE 迴圈實現自動重試 (最多 3 次)

DECLARE @Tries TINYINT = 1
WHILE @Tries <= 3
BEGIN
    BEGIN TRANSACTION
    BEGIN TRY
        INSERT Authors VALUES (@au_id, @au_lname, '', '', '', '', '', '11111', 0)
        WAITFOR DELAY '00:00:05'
        SELECT * FROM Authors WHERE au_lname LIKE 'Test%'
        COMMIT
        BREAK  -- 成功跳出
    END TRY
    BEGIN CATCH
        SELECT ERROR_NUMBER() AS ErrorNumber
        ROLLBACK
        SET @Tries = @Tries + 1
        CONTINUE  -- 重試
    END CATCH
END

**核心優勢:** 事務在迴圈**內部**開啟與結束,每次重試都是完整新事務。SQL 2000 做不到,錯誤 1205 建議 "Rerun the transaction" 卻無工具實現。现在 **T-SQL 內原生支援重試**。

其他死鎖緩解方案

  • SNAPSHOT ISOLATION / READ COMMITTED SNAPSHOT: 版本存儲避免讀寫阻塞。
  • 但 TRY/CATCH + 重試 是最靈活、可控、適用面最廣的工具。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved