----查看sql死鎖sql
CREATE procedure sp_who_lock
as
begin
declare @spid int
declare @blk int
declare @count int
declare @index int
declare @lock tinyint
set @lock=0
create table #temp_who_lock
(
id int identity(1,1),
spid int,
blk int
)
if @@error<>0 return @@error
insert into #temp_who_lock(spid,blk)
select 0 ,blocked
from (select * from master..sysprocesses where blocked>0)a
where not exists(select * from master..sysprocesses where a.blocked =spid and blocked>0)
union select spid,blocked from master..sysprocesses where blocked>0
if @@error<>0 return @@error
select @count=count(*),@index=1 from #temp_who_lock
if @@error<>0 return @@error
if @count=0
begin
select '沒有阻塞和死鎖信息'
return 0
end
while @index<=@count
begin
if exists(select 1 from #temp_who_lock a where id>@index and exists(select 1 from #temp_who_lock where id<=@index and a.blk=spid))
begin
set @lock=1
select @spid=spid,@blk=blk from #temp_who_lock where id=@index
select '引發數據庫死鎖的是: '+ CAST(@spid AS VARCHAR(10)) + '進程號,其執行的SQL語法以下'
select @spid, @blk
dbcc inputbuffer(@spid)
dbcc inputbuffer(@blk)
end
set @index=@index+1
end
if @lock=0
begin
set @index=1
while @index<=@count
begin
select @spid=spid,@blk=blk from #temp_who_lock where id=@index
if @spid=0
select '引發阻塞的是:'+cast(@blk as varchar(10))+ '進程號,其執行的SQL語法以下'
else
select '進程號SPID:'+ CAST(@spid AS VARCHAR(10))+ '被' + '進程號SPID:'+ CAST(@blk AS VARCHAR(10)) +'阻塞,其當前進程執行的SQL語法以下'
dbcc inputbuffer(@spid)
dbcc inputbuffer(@blk)
set @index=@index+1
end
end
drop table #temp_who_lock
return 0
end
GO數據庫
在查詢分析器中執行:app
exec sp_who_lockdom
----清理死鎖ide
/*--處理死鎖fetch
查看當前進程,或死鎖進程,並能自動殺掉死進程ui
由於是針對死的,因此若是有死鎖進程,只能查看死鎖進程
固然,你能夠經過參數控制,無論有沒有死鎖,都只查看死鎖進程spa
--鄒建 2004.4--*/線程
/*--調用示例指針
exec p_lockinfo
--*/
create proc p_lockinfo
@kill_lock_spid bit=1, --是否殺掉死鎖的進程,1 殺掉, 0 僅顯示
@show_spid_if_nolock bit=1 --若是沒有死鎖的進程,是否顯示正常進程信息,1 顯示,0 不顯示
as
declare @count int,@s nvarchar(1000),@i int
select id=identity(int,1,1),標誌,
進程ID=spid,線程ID=kpid,塊進程ID=blocked,數據庫ID=dbid,
數據庫名=db_name(dbid),用戶ID=uid,用戶名=loginame,累計CPU時間=cpu,
登錄時間=login_time,打開事務數=open_tran, 進程狀態=status,
工做站名=hostname,應用程序名=program_name,工做站進程ID=hostprocess,
域名=nt_domain,網卡地址=net_address
into #t from(
select 標誌='死鎖的進程',
spid,kpid,a.blocked,dbid,uid,loginame,cpu,login_time,open_tran,
status,hostname,program_name,hostprocess,nt_domain,net_address,
s1=a.spid,s2=0
from master..sysprocesses a join (
select blocked from master..sysprocesses group by blocked
)b on a.spid=b.blocked where a.blocked=0
union all
select '|_犧牲品_>',
spid,kpid,blocked,dbid,uid,loginame,cpu,login_time,open_tran,
status,hostname,program_name,hostprocess,nt_domain,net_address,
s1=blocked,s2=1
from master..sysprocesses a where blocked<>0
)a order by s1,s2
select @count=@@rowcount,@i=1
if @count=0 and @show_spid_if_nolock=1
begin
insert #t
select 標誌='正常的進程',
spid,kpid,blocked,dbid,db_name(dbid),uid,loginame,cpu,login_time,
open_tran,status,hostname,program_name,hostprocess,nt_domain,net_address
from master..sysprocesses
set @count=@@rowcount
end
if @count>0
begin
create table #t1(id int identity(1,1),a nvarchar(30),b Int,EventInfo nvarchar(255))
if @kill_lock_spid=1
begin
declare @spid varchar(10),@標誌 varchar(10)
while @i<=@count
begin
select @spid=進程ID,@標誌=標誌 from #t where id=@i
insert #t1 exec('dbcc inputbuffer('+@spid+')')
if @標誌='死鎖的進程' exec('kill '+@spid)
set @i=@i+1
end
end
else
while @i<=@count
begin
select @s='dbcc inputbuffer('+cast(進程ID as varchar)+')' from #t where id=@i
insert #t1 exec(@s)
set @i=@i+1
end
select a.*,進程的SQL語句=b.EventInfo
from #t a join #t1 b on a.id=b.id
end
go
-存儲過程
咱們可使用如下存儲過程來檢測,就能夠查出引發死鎖的進程和SQL語句。SQL Server自帶的系統存儲過程sp_who和sp_lock也能夠用來查找阻塞和死鎖, 但沒有這裏介紹的方法好用。
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
殺死鎖和進程
如何去手動的殺死進程和鎖?最簡單的辦法,從新啓動服務。可是這裏要介紹一個存儲過程,經過顯式的調用,能夠殺死進程和鎖。
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
用法以下:
exec p_killspid 'newdbpy'
查看鎖信息
如何查看系統中全部鎖的詳細信息?在企業管理管理器中,咱們能夠看到一些進程和鎖的信息,這裏介紹另一種
--查看鎖信息
create table #t(req_spid int,obj_name sysname)
declare @s nvarchar(4000)
,@rid int,@dbname sysname,@id int,@objname sysname
declare tb cursor for
select distinct req_spid,dbname=db_name(rsc_dbid),rsc_objid
from master..syslockinfo where rsc_type in(4,5)
open tb
fetch next from tb into @rid,@dbname,@id
while @@fetch_status=0
begin
set @s='select @objname=name from ['+@dbname+']..sysobjects where id=@id'
exec sp_executesql @s,N'@objname sysname out,@id int',@objname out,@id
insert into #t values(@rid,@objname)
fetch next from tb into @rid,@dbname,@id
end
close tb
deallocate tb
select 進程id=a.req_spid
,數據庫=db_name(rsc_dbid)
,類型=case rsc_type when 1 then 'NULL 資源(未使用)'
when 2 then '數據庫'
when 3 then '文件'
when 4 then '索引'
when 5 then '表'
when 6 then '頁'
when 7 then '鍵'
when 8 then '擴展盤區'
when 9 then 'RID(行 ID)'
when 10 then '應用程序'
end
,對象id=rsc_objid
,對象名=b.obj_name
,rsc_indid
from master..syslockinfo a left join #t b on a.req_spid=b.req_spid
go
drop table #t
select 0 spid ,'受阻於' 受阻於,blocked from (select * fromsysprocesses where blocked>0 ) a
where not exists(select * from (select * from sysprocesses whereblocked>0 ) b
where a.blocked=spid)
union select spid,'受阻於',blocked from sysprocesses whereblocked>0
--DBCC INPUTBUFFER (76) --查看進程ID執行內容
select Pid=a.req_spid,Db=db_name(rsc_dbid),Type=case rsc_type when 1then 'NULL'
when 2 then 'DB' when 3 then 'File'when 4 then 'Indx' when 5 then 'Tabl' when 6 then 'Page'
when 7 then 'Key' when 8 then'ExDiskArea' when 9 then 'RowID' when 10 then 'App' end,
rsc_indid,Objid=rsc_objid,ObjName=(select name from['dbname']..sysobjects where id=a.rsc_objid)
from master..syslockinfo a --查看進程較多信息 [dbname 替換成你要監控的db]
當你獲得相關信息後確定能夠kill的ID便可動手了,這個就很簡單了