我正在尝试解决一个复杂的死锁问题。
有两个单独的进程(服务和代理作业),它们通常同时执行相同的SP,但具有不同的@BatchID参数。此SP在显式BEGIN TRAN中调用。SP中有30种不同的Insert/Update语句。这两个进程每天在相同的表/索引上死锁5次,每天大约相同的时间,而服务进程始终是受害者。该表有许多不必要的/冗余索引和两个Insert/Update触发器。锁定升级被禁用。
死锁图:

死锁声明:

我们知道幸存者/受害者是SQL会话(SPID),而不是SQL语句。
我们还知道,两个会话的Frame1中显示的UPDATE语句都与死锁有关。他们是怎么参与的?它们都是索引键U锁的请求者。到目前为止我是否正确..。
但是,哪些声明是所有者?他们什么时候开始持有索引键上的X锁的?
解决/减少死锁的标准建议之一是缩短事务。
但是,如果有100条类似的语句,而不知道哪条语句开始持有锁以及何时开始,那么缩短事务是不容易的。
发布于 2017-11-10 14:25:40
问题1:但是谁是业主呢?
语句没有锁。交易拥有锁。
他们什么时候开始持有索引键上的X锁的?
死锁图或DMVs中没有什么能告诉你这一点。该信息仅在跟踪事件或XEvent中可用,此时获取锁。
是仅在满足UPDATE WHERE子句的行上保持的键锁,还是保存在与索引中的值匹配的所有值上
update使用U锁读取,然后转换为X锁以更新。
它会通过在更新中添加(TABLOCK)而消失吗?
可能吧。解决死锁的一个关键策略是更早更大地锁定。只有当两个会话获得兼容的锁,然后尝试获取不兼容的锁时,才会出现死锁。如果事务中的第一个锁是不兼容的,那么第二个会话将等到第一个提交才获得其第一个锁。
在合适的粒度上获取锁的一个简单方法是使用服务提供商_getapplock来使用应用程序锁。如果您决定事务A和B不能同时运行,那么只需让每个事务在开始时获得相同的应用程序锁,它们就会按顺序运行。
https://dba.stackexchange.com/questions/190613
复制相似问题