SQL Server中同一个事务中对同一个表先后进行修改和删除导致死锁的解决方案

执行SQL
两个会话执行的SQL如下,逐条执行(即非两个语句一起执行)。
begin tran
update t_wf_mapstatemqstore set FSTATUS='0' where FACTINSTID='PUR_PurchaseOrder_266879'
delete from t_wf_mapstatemqstore where FACTINSTID='PUR_PurchaseOrder_266879'
rollback
两个会话修改同一条记录,按正常的理解,update操作会放置排他锁,从而导致其他会话阻塞,不应该发生死锁才对。但实际上地方确发生了。
死锁信息

从上图可以得到下面信息:
会话63执行delete语句,对FACTINSTID='PUR_PurchaseOrder_266879'记录拥有X锁,其需要的资源被会话375持有;会话375执行update语句,对FACTINSTID='PUR_PurchaseOrder_266879'记录拥有U锁,其需要的资源被会话63持有。从而引起死锁。
按正常理解,两个会话访问表的顺序一致,并且修改和删除的是同一行记录,理论上应该会产生阻塞而非死锁。
但有一种情况,建立了多个索引的情况下,是可能由于索引的交叉引起死锁的,接下来看看是否属于这种情形。
检查索引定义情况

可以看到,出了主键外,还有两个索引,而上面的语句中,使用的为FACTINSTID对应的唯一索引。删除会触发对主键的删除(由于主键是聚集索引,数据存储按主键顺序存储),而主键删除时同时会导致其他索引结构的更新。
查看锁资源对应的信息
l 锁资源信息
KEY: 8:72059079959511040 (8423a987d5eb) CleanCnt:2 Mode:X Flags: 0x1
KEY: 8:72059079959642112 (4bccc93b42dd) CleanCnt:2 Mode:U Flags: 0x1
l 查看其对应的值
select partition_id,object_name(object_id),index_id from sys.partitions where object_i
SQL Server中同一个事务中对同一个表先后进行修改和删除导致死锁的解决方案
声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。如若本站内容侵犯了原著者的合法权益,可联系本站删除。



