日期:2014-05-18  浏览次数:20443 次

这种死锁的原因是什么
一个网站程序,访问比较频繁;主要是update更新数据的时候,发生“事务(进程   ID   75)与另一个进程已被死锁在   lock   |   communication   buffer   资源上,且该事务已被选作死锁牺牲品。请重新运行该事务。”

用网上找到的一个查找死锁原因的sql试了,结果如下:

进程号SPID:55被进程号SPID:65阻塞(死锁),其当前进程执行的SQL语法如下
EventType       Parameters       EventInfo
PRC   Event       0                         sp_cursor;1

------解决方案--------------------
查查程序有无互相调用的情况,如A表的触发器调用B表,B表的触发器又调用C表,C表的触发器由调用A表。如果多人同时更新同一个表,不可能死锁吧
------解决方案--------------------
是不是在修改主键信息啊
------解决方案--------------------
ding
------解决方案--------------------
--可以用鄒健的存儲過程查看死鎖時的SQL語句,對其進行分析即可找到原因
/*--處理鎖死

查看當前進程,或鎖死進程,並能自動殺掉死進程

因為是針對死的,所以如果有鎖死進程,只能查看鎖死進程
當然,你可以通過參數控制,不管有沒有鎖死,都只查看鎖死進程

--調用示例

exec SP_Sys_LockInfo
--*/
CREATE proc SP_Sys_LockInfo
@kill_lock_spid bit=0, --是否殺掉鎖死的進程,1 殺掉, 0 僅顯示
@show_spid_if_nolock bit=1 --如果沒有鎖死的進程,是否顯示正常進程資訊,1 顯示,0 不顯示
as
declare @count int,@s nvarchar(4000),@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(3500))
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


------解决方案--------------------
其实所有的死锁最深层的原因就是一个:资源竞争
表现一:
一个用户A 访问表A(锁住了表A),然后又访问表B
另一个用户B 访问表B(锁住了表B),然后企图访问表A
这时用户A由于用户B已经锁住表B,它必须等待用户B释放表B,才能继续,好了他老人家就只好老老实实在这等了
同样用户B要等用户A释放表A才能继续这就死锁了
解决方法:
这种死锁是由于你的程序的BUG产生的,除了调整你的程序的逻辑别无他法