出現死鎖的解決辦法
-
在master中創建查看死鎖的存儲過程
- use master
- go
- create procedure sp_who_lock
- as
- begin
- declare @spid int,@bl int,
- @intTransactionCountOnEntry int,
- @intRowcount int,
- @intCountProperties int,
- @intCounter int
- create table #tmp_lock_who (
- id int identity(1,1),
- spid smallint,
- bl smallint)
- IF @@ERROR<>0 RETURN @@ERROR
- insert into #tmp_lock_who(spid,bl) select 0 ,blocked
- from (select * from sysprocesses where blocked>0 ) a
- where not exists(select * from (select * from sysprocesses where blocked>0 ) b
- where a.blocked=spid)
- union select spid,blocked from sysprocesses where blocked>0
- IF @@ERROR<>0 RETURN @@ERROR
- -- 找到臨時表的記錄數
- select @intCountProperties = Count(*),@intCounter = 1
- from #tmp_lock_who
- IF @@ERROR<>0 RETURN @@ERROR
- if @intCountProperties=0
- select '現在沒有阻塞和死鎖信息' as message
- -- 循環開始
- while @intCounter <= @intCountProperties
- begin
- -- 取第一條記錄
- select @spid = spid,@bl = bl
- from #tmp_lock_who where Id = @intCounter
- begin
- if @spid =0
- select '引起數據庫死鎖的是: '+ CAST(@bl AS VARCHAR(10)) + '進程號,其執行的SQL語法如下'
- else
- select '進程號SPID:'+ CAST(@spid AS VARCHAR(10))+ '被' + '進程號SPID:'+ CAST(@bl AS VARCHAR(10)) +'阻塞,其當前進程執行的SQL語法如下'
- DBCC INPUTBUFFER (@bl )
- end
- -- 循環指針下移
- set @intCounter = @intCounter + 1
- end
- drop table #tmp_lock_who
- return 0
- end
在master中創建刪除指定數據庫的死鎖的存儲過程
- use master
- go
- if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_killspid]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
- drop procedure [dbo].[p_killspid]
- GO
- create proc p_killspid
- @dbname varchar(200) --要關閉進程的數據庫名
- as
- declare @sql nvarchar(500)
- declare @spid nvarchar(20)
- declare #tb cursor for
- select spid=cast(spid as varchar(20)) from master..sysprocesses where dbid=db_id(@dbname)
- open #tb
- fetch next from #tb into @spid
- while @@fetch_status=0
- begin
- exec('kill '+@spid)
- fetch next from #tb into @spid
- end
- close #tb
- deallocate #tb
- go
避免死鎖
-
按同一順序訪問對象
如果所有並發事務按同一順序訪問對象,則發生死鎖的可能性會降低。例如,如果兩個並發事務獲得 Supplier 表上的鎖,然后獲得 Part 表上的鎖,則在其中一個事務完成之前,另一個事務被阻塞在 Supplier 表上。第一個事務提交或回滾后,第二個事務繼續進行。不發生死鎖。將存儲過程用於所有的數據修改可以標准化訪問對象的順序。
-
避免事務中的用戶交互
避免編寫包含用戶交互的事務,因為運行沒有用戶交互的批處理的速度要遠遠快於用戶手動響應查詢的速度,例如答復應用程序請求參數的提示。例如,如果事務正在等待用戶輸入,而用戶去吃午餐了或者甚至回家過周末了,則用戶將此事務掛起使之不能完成。這樣將降低系統的吞吐量,因為事務持有的任何鎖只有在事務提交或回滾時才會釋放。即使不出現死鎖的情況,訪問同一資源的其它事務也會被阻塞,等待該事務完成。
-
保持事務簡短並在一個批處理中
在同一數據庫中並發執行多個需要長時間運行的事務時通常發生死鎖。事務運行時間越長,其持有排它鎖或更新鎖的時間也就越長,從而堵塞了其它活動並可能導致死鎖。
保持事務在一個批處理中,可以最小化事務的網絡通信往返量,減少完成事務可能的延遲並釋放鎖。
-
使用低隔離級別
確定事務是否能在更低的隔離級別上運行。執行提交讀允許事務讀取另一個事務已讀取(未修改)的數據,而不必等待第一個事務完成。使用較低的隔離級別(例如提交讀)而不使用較高的隔離級別(例如可串行讀)可以縮短持有共享鎖的時間,從而降低了鎖定爭奪。
- ALTER DATABASE [dbname]
- SET READ_COMMITTED_SNAPSHOT ON
使用綁定連接
使用綁定連接使同一應用程序所打開的兩個或多個連接可以相互合作。次級連接所獲得的任何鎖可以象由主連接獲得的鎖那樣持有,反之亦然,因此不會相互阻塞。
轉載:https://blog.csdn.net/YKPkaiping/article/details/38068463