SQL_Server 2005中解決死鎖問題

數據庫操作的死鎖是不可避免的,本文並不打算討論死鎖怎樣產生,重點在於解決死鎖,通過SQL Server 2005, 現在似乎有了一種新的解決辦法。


  將下面的SQL語句放在兩個不同的連接裏面,並且在5秒內同時執行,將會發生死鎖。


use Northwind

begin tran

insert intoOrders(CustomerId) values(@#ALFKI@#)

waitfordelay @#00:00:05@#

select *from Orders where CustomerId = @#ALFKI@#

commit

print @#end tran@#



SQL Server對付死鎖的辦法是犧牲掉其中的一個,拋出異常,並且回滾事務。在SQLServer 2000,語句一旦發生異常,T-SQL將不會繼續運行,上面被犧牲的連接中, print @#endtran@#語句將不會被運行,所以我們很難在SQL Server 2000T-SQL中對死鎖進行進一步的處理。


  現在不同了,SQLServer 2005能夠在T-SQL中對異常進行捕獲,這樣就給我們提供了一條處理死鎖的途徑:


  下面利用的try ...catch來解決死鎖。


SET XACT_ABORT ON

declare @r int

set @r = 1

while @r <= 3

begin

begin tran


begin try

insertinto Orders(CustomerId) values(@#ALFKI@#)

waitfordelay @#00:00:05@#

select *from Orders where CustomerId = @#ALFKI@#


commit

break

end try


begin catch

rollback

waitfordelay @#00:00:03@#

set @r =@r + 1

continue

end catch

end



  解決方法當然就是重試,但捕獲錯誤是前提。rollback後面的waitfor不可少,發生衝突後需要等待一段時間,@retry數目能夠調整以應付不同的需要。


  但是現在又面臨一個新的問題: 錯誤被掩蓋了,一但問題發生並且超過3次,異常卻不會被拋出。SQLServer 2005 有一個RaiseError語句,能夠拋出異常,但卻不能直接拋出原來的異常,所以需要重新定義發生的錯誤,現在,解決方案變成了這樣:


declare @r int

set @r = 1

while @r <= 3

begin

begin tran


begin try

insertinto Orders(CustomerId) values(@#ALFKI@#)

waitfordelay @#00:00:05@#

select *from Orders where CustomerId = @#ALFKI@#


commit

break

end try


begin catch

rollback

waitfordelay @#00:00:03@#

set @r =@r + 1

continue

end catch

end

if ERROR_NUMBER() <> 0

begin

declare@ErrorMessage nvarchar(4000);

declare@ErrorSeverity int;

declare@ErrorState int;

select

@ErrorMessage= ERROR_MESSAGE(),

@ErrorSeverity= ERROR_SEVERITY(),

@ErrorState= ERROR_STATE();

raiserror(@ErrorMessage,

@ErrorSeverity,

@ErrorState

);

end

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