如何使用 TRY CATCH 語句避免死鎖

2021-09-04 11:49:01 字數 2608 閱讀 3994

死鎖是正常現象不可避免。發生死鎖會犧牲乙個程序並回滾事務,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 內部完成。

如何使用 TRY CATCH 語句避免死鎖

死鎖是正常現象不可避免。發生死鎖會犧牲乙個程序並回滾事務,sql不會自己重試,需要用try catch和waitfor實現重試。具體方法如下 如何使用 try catch 語句避免死鎖 現在,讓我們來使用 try catch 語句修改 正文。對於本示例,需要以 sql server 2005 版本執...

如何使用 TRY CATCH 語句避免死鎖

死鎖是正常現象不可避免。發生死鎖會犧牲乙個程序並回滾事務,sql不會自己重試,需要用try catch和waitfor實現重試。具體方法如下 如何使用 try catch 語句避免死鎖 現在,讓我們來使用 try catch 語句修改 正文。對於本示例,需要以 sql server 2005 版本執...

如何使用 TRY CATCH 語句避免死鎖

如何使用 try catch 語句避免死鎖 現在,讓我們來使用 try catch 語句修改 正文。對於本示例,需要以 sql server 2005 版本執行 使用 try catch 時,操作 和錯誤處理 是分開的。您應該將執行乙個操作的 放在 try 語句塊中,將錯誤處理 放在 catch 語...