1

我有一个死锁的问题..

我正在尝试为我的数据库的更新提供 sql 依赖项。

我通过在一系列表上创建触发器来做到这一点。修改表时,我在辅助表中增加一个整数,例如。[dbo].[计数器]。然后我在这个表上放置一个 SQL 依赖项,以了解哪个表是从代码更新的。

但是,我放置触发器的目标表可以在事务中使用,在这种情况下,很容易使事务死锁。

即 tbl1 在插入/更新/删除时触发以更新计数器表 tbl2 在插入/更新/删除时触发以更新计数器表

事务 A 发生在 thread1 tbl1 被修改,触发了 counter 表的更新

事务 B 发生在线程 2 tbl2 被修改,这触发了计数器表的更新,线程 2 现在被阻塞等待线程 1

同时在 thread1 上,事务 A 继续,并更新另一个表(tbl1 或 tbl2)

现在发生死锁,其中一个线程被选为受害者。

我的问题是,是否有更好的方法来创建触发器以消除死锁的可能性?任何人都知道 ASP.NET 中的默认 SQLDependency 如何解决这个问题?

4

2 回答 2

1

你能容忍未使用的计数器值吗?如果是这样,只需在更新计数器时退出事务。

于 2013-01-25T23:46:20.607 回答
1

好的总结一下,

死锁是由不同的事务在递增表上同时获取范围锁和行锁引起的。

ASP.NET SQLDependency 对触发器使用 ROWLOCK 提示来消除死锁情况。然而,这引入了阻塞行为,因此如果 2 个事务正在修改同一个递增表,则这些事务本质上是序列化的。

MS Support 的建议是将 ROWLOCK 提示更改为 READPAST。如果同时修改递增表中的不同行,这会减少阻塞行为。

由于通知不需要 RDBMS 的绝对 ACID 属性,因此一种高级策略可能是使用非阻塞全局变量(如 context_info)作为一组二进制标志来存储行已更改的事实(这将消除同一行的阻塞)表),但是需要对调用应用程序进行逻辑更改以处理和重置变量。

于 2013-02-01T17:22:24.993 回答