数据库中的死锁问题
在数据库中经常会遇到这样的情况:一个主表A,一个子表B,B表中包含有A表的主键作为外键。当要插入数据的时候,我们会先插入A表,然后获得A表的Identity,再插入B表。如果要进行删除操作,那么就先删除子表B,然后再删除主表A。在程序设计中,对两个表的操作是在一个事务之中完成的。
当系统使用频繁就会出现插入操作和删除操作同时进行的情况。这个时候插入事务会先将主表A放置独占锁,然后去访问子表B,而同时删除事务会对子表B放置独占锁,然后去访问主表A。插入事务会一直独占着A表,等待访问B表,删除事务也一直独占着B表等待访问A表,于是两个事务相互独占一个表,等待对方释放资源,这样就造成了死锁。
说道死锁问题的解决,一般情况下我们都是选择KILL进程,但如果不查出引起死锁的原因,死锁的现象则会频繁出现,其实只要通过查找引起死锁的操作,就可以方便的解决死锁。
具体的解决方法如下:
1.再死锁发生时,我们可以通过下面的语法,查询到引起死锁的操作
use master
go
declare @spid int,@bl int
DECLARE s_cur CURSOR FOR
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
OPEN s_cur
FETCH NEXT FROM s_cur INTO @spid,@bl
WHILE @@FETCH_STATUS = 0
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 )
FETCH NEXT FROM s_cur INTO @spid,@bl
end
CLOSE s_cur
DEALLOCATE s_cur
exec sp_who2
/*
2.然后查找程序/数据库,此t_sql语法具体在什么地方使用。
3.分析已经找到的,解决问题。
EG:
*/
/*
-------------------------------------------------------
引起数据库死锁的是: 71进程号,其执行的SQL语法如下
EventType Parameters EventInfo
-------------- ---------- ------------------------------
Language Event 0
select * from test
insert test values(1,2)
(所影响的行数为 1 行)
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
------------------------------------------------------------
进程号SPID:64被进程号SPID:71阻塞,其当前进程执行的SQL语法如下
EventType Parameters EventInfo
-------------- ---------- ---------------------------------
Language Event 0
select * from test
insert test values(1,2)
(所影响的行数为 1 行)
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
-------------------------------------------------------------
进程号SPID:65被进程号SPID:64阻塞,其当前进程执行的SQL语法如下
EventType Parameters EventInfo
-------------- ---------- -------------------------------------
Language Event 0 begin tran
select * from test with (holdlock)
waitfor time '12:00'
select * from test
commit
(所影响的行数为 1 行)
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
-------------------------------------------------------
进程号SPID:73被进程号SPID:64阻塞,其当前进程执行的SQL语法如下
EventType Parameters EventInfo
-------------- ---------- ------------------------------
Language Event 0 begin tran
select * from test with (holdlock)
waitfor time '12:00'
select * from test
commit
(所影响的行数为 1 行)
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
*/
文章来源: baike.duba.net
go
declare @spid int,@bl int
DECLARE s_cur CURSOR FOR
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
OPEN s_cur
FETCH NEXT FROM s_cur INTO @spid,@bl
WHILE @@FETCH_STATUS = 0
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 )
FETCH NEXT FROM s_cur INTO @spid,@bl
end
CLOSE s_cur
DEALLOCATE s_cur
exec sp_who2
/*
2.然后查找程序/数据库,此t_sql语法具体在什么地方使用。
3.分析已经找到的,解决问题。
EG:
*/
/*
-------------------------------------------------------
引起数据库死锁的是: 71进程号,其执行的SQL语法如下
EventType Parameters EventInfo
-------------- ---------- ------------------------------
Language Event 0
select * from test
insert test values(1,2)
(所影响的行数为 1 行)
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
------------------------------------------------------------
进程号SPID:64被进程号SPID:71阻塞,其当前进程执行的SQL语法如下
EventType Parameters EventInfo
-------------- ---------- ---------------------------------
Language Event 0
select * from test
insert test values(1,2)
(所影响的行数为 1 行)
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
-------------------------------------------------------------
进程号SPID:65被进程号SPID:64阻塞,其当前进程执行的SQL语法如下
EventType Parameters EventInfo
-------------- ---------- -------------------------------------
Language Event 0 begin tran
select * from test with (holdlock)
waitfor time '12:00'
select * from test
commit
(所影响的行数为 1 行)
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
-------------------------------------------------------
进程号SPID:73被进程号SPID:64阻塞,其当前进程执行的SQL语法如下
EventType Parameters EventInfo
-------------- ---------- ------------------------------
Language Event 0 begin tran
select * from test with (holdlock)
waitfor time '12:00'
select * from test
commit
(所影响的行数为 1 行)
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
*/
文章来源: baike.duba.net