我们正试图追查一个死锁问题。我有一个从 Profiler 生成的死锁图 (xdl)。它将丢失的 SQL 语句显示为简单的 Select 语句,而不是 Update、Delete 或 Insert 语句。该图将失败的 Select 语句显示为请求资源上的共享锁**但还拥有资源上的更新锁**
。这让我感到困惑。为什么不属于插入、更新或删除的 Select 语句会在资源上持有更新锁?
我应该补充一点,它拥有的更新锁位于被失败的 Select 语句选择的表上。
编辑:请不要建议使用 NoLock。是的,这将解决问题,但引入了一个新问题——脏读问题。此查询正在访问生产服务器。我真正想知道的是为什么 Select 语句会发出更新锁。
最佳答案
你确定 SELECT 拥有 U 锁?
如您所知,U 和 X 锁(以及可序列化的 S 锁)在 事务 期间而不是语句期间持有。因此,从先前执行的语句中发出写入的事务完全有可能拥有 U 锁。为什么它拥有一个 U 锁,而不是一个 X 锁(即它拥有一个 U 锁没有升级到 X),这本身就是一个谜,但我可以设想这可能发生的几种方式。
因此,如果 SELECT 语句是多语句事务的一部分,那么它完全有可能拥有 X/U 锁。一个带有 U 形锁的独立 SELECT,我认为这有点不寻常。
典型的 SELECT 与 UPDATE 死锁发生在索引访问顺序场景中,如 Read/Write deadlock 中描述的情况。 .我相信您对死锁图进行了认真的阅读,但是如果要求不高,您可以分享一下吗?
哦,顺便说一句,你考虑过读取提交的快照吗?
关于sql-server - 由于更新锁导致的死锁问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2814377/