您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“sql中怎么使用TRY/CATCH語句避免死鎖”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“sql中怎么使用TRY/CATCH語句避免死鎖”這篇文章吧。
死鎖是正常現象不可避免。發生死鎖會犧牲一個進程并回滾事務,SQL不會自己重試,需要用TRY/CATCH和WAITFOR實現重試。具體方法如下
如何使用 TRY/CATCH 語句避免死鎖
現在,讓我們來使用 TRY/CATCH 語句修改代碼正文。(對于本示例,需要以 SQL Server 2005 版本運行代碼。)使用 TRY/CATCH 時,操作代碼和錯誤處理代碼是分開的。您應該將執行一個操作的代碼放在 TRY 語句塊中,將錯誤處理代碼放在 CATCH 語句塊中。如果 TRY 語句塊中的代碼執行失敗,代碼執行將跳到 CATCH 語句塊。(除了那些防礙整個批處理運行的錯誤(如,丟失對象),該方法幾乎適用于所有的錯誤。)
以下示例使用 TRY/CATCH 語句對前面使用的代碼進行了改寫。代碼標題相同,但是代碼正文不同:
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
ROLLBACK
END CATCH;
SELECT @@TRANCOUNT AS '@@Trancount'
現在,在連接到 SQL Server 2005 的并列窗口中運行這些代碼,在此之前您需要確認已經刪除了 authors 表格中任何可能阻止插入操作的數據;或者,您可以使用前置 DELETE 語句。
兩個窗口返回的 @@TRANCOUNT 級別都為 0,這表明仍然發生了死鎖,但 TRY/CATCH 語句捕獲了這次發生的死鎖。死鎖犧牲品的批處理沒有再次中止,可在它的輸出結果中看到錯誤:
ErrorNumber
-----------
1205
@@Trancount
-----------
0
您應該已經發現 TRY/CATCH 語句具有的威力了。因為死鎖錯誤能夠為 CATCH 語句塊所捕獲,所以批處理將不再中止,T-SQL 代碼也能繼續執行。對于死鎖犧牲品而言,死鎖錯誤 1205 將代碼放入 CATCH 語句塊 — 在這里您可以使用新的錯誤處理函數瀏覽死鎖錯誤。前置代碼僅使用 ERROR_NUMBER() 函數取代 @@ERROR 變量,您也可以使用 ERROR_MESSAGE()、 ERROR_PROCEDURE()、ERROR_SEVERITY() 和 ERROR_STATE()。這些函數的功能一目了然,它們提供的功能比我們以往使用的更多。
請注意,這個前置 CATCH 語句塊包含一個 ROLLBACK。這樣做的原因是,即使捕獲了死鎖錯誤,事務也不會回滾。事務仍然要失敗,但是,現在您有責任在 TRY/CATCH 語句中回滾事務。那么,區別在哪里?盡管您不能使事務繼續進行,但是您能夠重試事務!
在 TRY/CATCH 語句中進行重試
在 SQL Server 2000 的 T-SQL 中,錯誤 1205 令人沮喪之處是它提供的建議:“Rerun the transaction.”問題是,至少在 SQL Server 2000 的 T-SQL 中,您不能做到這一點。但是,由于 SQL Server 2005 的 TRY/CATCH 為我們提供了捕獲死鎖錯誤的方法,現在,重試事務是可能實現的。
以下代碼正文說明了一種執行重試操作的方法。這段代碼仍然使用與前面相同的標題:
DECLARE @Tries tinyint
SET @Tries = 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
這段代碼的功能是通過一個 WHILE 循環添加一個重試操作。我將重試次數設置為 3,重試次數是可以配置的。至少我們現在有了一種在 T-SQL 內重試一個死鎖犧牲品代碼的方法 — 這是我們過去一直無法做到的。
但是,需要注意整個事務是在 WHILE 循環內進行的 — 而不是在循環外部。因此執行循環時,事務不僅在每個循環體內部開始,而且也在其中結束 — 不是 TRY 語句塊執行完畢,返回一個 COMMIT,就是 CATCH 語句塊執行,返回一個 ROLLBACK。如果 TRY 成功,TRY 語句塊將以一個 BREAK 語句結束,退出 WHILE 循環。否則,CATCH 語句塊將重試計數器加 1,以一個 CONTINUE 語句結束本次循環,重新執行下次 WHILE 循環。事實上,您有實現重試事務的代碼 — 就像錯誤 1205 告訴我們做的那樣。但現在,重試操作完全在 T-SQL 內部完成。
sql Server 2005 也提供幫助解決死鎖問題的其他方法,例如 SNAPSHOT ISOLATION 級別和用于 READ COMMITTED 的新選項(稱為 READ COMMITTED SNAPSHOT)。然而,這一事實 — 現在,通過 SQL Server 2005,您能夠對事務進行編碼并捕獲死鎖錯誤(并重試它們) — 已經意味著您擁有一個可任意支配、功能更加強大的工具。
以上是“sql中怎么使用TRY/CATCH語句避免死鎖”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。