SQL Server 2008 R2 DeadLock on query Notification (SqlDepend



我在SQL Server 2008 R2上遇到了死锁问题。在SQL事件探查器中查看死锁图时,问题似乎源于查询通知:

  <resource-list>
   <keylock hobtid="72057654759522304" dbid="6" objectname="MyDB.sys.query_notification_814081939" indexname="cidx" id="lock15ab2aa80" mode="RangeX-X" associatedObjectId="72057654759522304">
    <owner-list>
     <owner id="process5c5708" mode="RangeX-X"/>
    </owner-list>
    <waiter-list>
     <waiter id="process4e9ae08" mode="RangeS-U" requestType="wait"/>
    </waiter-list>
   </keylock>
   <keylock hobtid="72057654759522304" dbid="6" objectname="MyDB.sys.query_notification_814081939" indexname="cidx" id="lock15e56a300" mode="RangeS-U" associatedObjectId="72057654759522304">
    <owner-list>
     <owner id="process4e9ae08" mode="RangeS-U"/>
    </owner-list>
    <waiter-list>
     <waiter id="process5c5708" mode="RangeS-U" requestType="wait"/>
    </waiter-list>
   </keylock>
  </resource-list>

这些查询通知是使用 SQLDependency 实现的。更新由 SQLDependency 监视的表时似乎发生了死锁。

我真的不明白死锁图语法。.KeyLock 模式仅在使用可序列化事务隔离级别时为 RangeS-U。,对吧?

我也读过这个问题...我应该激活READ_COMMITED_SNAPSHOT吗?

感谢。。。

肯定不能确定它,但这里有一些想法......

导致通知的语句在传递通知之前可能无法完成。因此,在从服务代理接收通知并对通知执行任何操作时,它可能仍具有活动锁。

也许您的通知收件人正在尝试清理队列或在生成第一个通知的事务完成之前从队列中获取第二个通知。

生成通知的 DML 是否在多步骤事务中运行?接收在多步骤事务中运行的通知的代码。(即你是否使用了 begin tran 或等效的?

跟踪死锁图中提到的进程并了解哪些代码持有 RangeX-X 锁,哪些代码持有 RangeS-U 可能很有用。

您可能希望发布一些生成通知的代码和接收通知的代码的最小示例。

此外,这里还有一个 Microsoft KB,介绍了通知和多个订阅的已知类似死锁问题。

MS KB975090 可能是相关的,但不完全相同。

这背后的主要原因是事务太长并且涉及太多对象。

正如我在问题中所说,触发 SqlDependency 的表包含对数据库中每个对象的引用。更新同一事务中的一堆对象意味着查询通知系统锁定此大表。因此,您很快就会陷入僵局。

2 种解决方案(由 MS 建议):

  • 减少事务的长度和复杂性。
  • 在大事务之外执行触发通知系统的请求。

最新更新