专注,勤学,慎思。戒骄戒躁,谦虚谨慎

just do it

导航

SQL Server并发操作单个表时发生在page页面级的死锁

 

最近遇到的死锁问题都发生在并发操作单张表上,比较有意思,就模拟了重现了一下。
根据非聚集索引为条件,删除某一个表的数据,类似于这么一个语句,delete from table where nocluster_index in (x,y,z,m,n……)in里面的内容不同,并发执行
某些情况下,可能会引发死锁,如下简单模拟重现一下这种情况。

 

如下用两张表来模拟上述场景:TestPageLock代表要删除的表,TestId来存储用来删除的Id

 

如下,用两个Session即可,模拟并发,很快就会看到一条死锁的信息

 

扩展事件ring_buffer target中中的死锁日志

原理不难理解:
不同的Session要删除的数据分布在不同的数据页面中,执行delete语句删除数据的情况下,也是一个查找然后加锁的过程
当要删除的数据落在不同的数据页面上的时候,一旦加锁顺序发生冲突,就会产生死锁
比如Session1删除的数据分布在50,80,120页面上,Session2删除的数据分布在100,120,140页面上,
Session1和Session2 要加锁的目标存在交集,一旦存在交集,并发情况就可能存在加锁顺序冲突,类似死锁因此而产生

 

解决:
最最简单暴力的就是显式锁提示,这里只能是tablockx;高级一点,遇到类似并发业务,可以使用队列进行排队。
估计会有人担心tablockx的性能问题会不会锁的太多了,测试发现直接显式tablockx锁提示,并不会非常大地影响性能,整体性能甚至会变高,
因为tablockx锁模式更加简单直接,会比行数需要的资源更少,因此在锁定资源上,处理起来比较高效。

 

posted on 2018-09-12 14:54  MSSQL123  阅读(992)  评论(2编辑  收藏  举报