Dal*_*e K 16 sql-server deadlock locking
我有 2 个查询,当同时运行时会导致死锁。
查询 1 - 更新包含在索引 (index1) 中的列:
update table1 set column1 = value1 where id = @Id
Run Code Online (Sandbox Code Playgroud)
在 table1 上使用 X-Lock,然后在 index1 上尝试 X-Lock。
查询 2:
select columnx, columny, etc from table1 where {some condition}
Run Code Online (Sandbox Code Playgroud)
在 index1 上使用 S-Lock,然后在 table1 上尝试 S-Lock。
有没有办法在保持相同查询的同时防止死锁?例如,我可以在更新之前以某种方式在更新事务中的索引上使用 X-Lock 以确保表和索引访问的顺序相同 - 这应该防止死锁?
隔离级别为 Read Committed。为索引启用了行锁和页锁。同一个记录可能同时参与了两个查询 - 我无法从死锁图中判断出来,因为它没有显示参数。
Pau*_*ite 16
有没有办法在保持相同查询的同时防止死锁?
死锁图显示此特定死锁是与书签查找(在本例中为 RID 查找)关联的转换死锁:
正如问题所指出的,由于查询可能以不同的顺序在相同资源上获得不兼容的锁,因此会出现一般死锁风险。该SELECT
查询需要访问表之前的指数,由于RID查询,而UPDATE
查询修改表,然后再索引。
消除死锁需要去除死锁成分之一。以下是主要选项:
SELECT
查询返回 26 列。Proposal
。这是值得考虑的,尽管此列似乎是类型uniqueidentifier
,这可能是也可能不是聚集索引的好选择,具体取决于更广泛的问题。READ_COMMITTED_SNAPSHOT
或SNAPSHOT
数据库选项避免在读取时使用共享锁。这需要仔细测试,尤其是对于任何设计的阻塞行为。触发代码还需要测试以确保逻辑正确执行。READ UNCOMMITTED
对SELECT
查询使用隔离级别,避免在读取时使用共享锁。所有通常的警告都适用。我可以在更新之前以某种方式对更新事务中的索引进行 X-Lock 以确保表和索引访问的顺序相同吗
你可以试试这个,通过在显式事务包装更新,并执行SELECT
与XLOCK
在更新之前的非聚集索引值提示。这依赖于您确定地知道非聚集索引中的当前值是什么,获得正确的执行计划,并正确预测获取这个额外锁的所有副作用。它还依赖于锁定引擎不够聪明,无法避免在判断为多余的情况下获取锁定。
总之,虽然这在原则上是可行的,但我不建议这样做。很容易错过一些东西,或者以创造性的方式超越自己。如果您真的必须避免这些死锁(而不仅仅是检测它们并重试),我鼓励您查看上面列出的更通用的解决方案。