0

我的一位同事有一个存储过程,它执行以下
Begin tran
1) 动态生成一个 select 语句。
2) Insert into table x
3) 执行 select 语句
End tran

如果此存储过程由两个分隔线程同时运行,他会收到以下错误: System.Data.SqlClient.SqlException: Transaction (Process ID 57) was deadlocked on lock | 与另一个进程通信缓冲区资源,并已被选为死锁牺牲品。重新运行事务

这个存储过程真的是问题吗?从我天真的想法来看,这看起来更像是一种竞争条件,而不是僵局。

4

2 回答 2

1

两个“先写后读”的序列肯定会死锁。您在帖子中省略了一些“细节”,例如发生死锁的实际资源是什么以及涉及的请求。我们将坐在我们的裤子上,在字里行间阅读,从这样一个记录不充分的帖子中弥补了大部分案例:

  1. 交叉读写。线程 1 插入带有键 A 的行,然后选择带有键 B 的行。线程 2 插入带有键 B 的行,然后选择带有键 A 的行。执行顺序是 T1(A),T2(B),T1(B)-等待,T2 (A)-死锁。
  2. 独立读写:T1 插入 A 然后读取 A,T2 插入 B 然后读取 B。关键信息:键上没有索引,因此需要进行表扫描来读取 A 和/或B。执行顺序是 T1 写 A,T2 写 B,T1 读 A,开始扫描,阻塞 T2 在 B 上的 X-lock,T2 读 B,开始扫描,阻塞 T1 在 A 上的 X-lock,死锁。
  3. 独立优化的写读。对于大多数新手来说,这种情况是最令人困惑的,当适当的访问索引到位但仍然发生死锁时。我已经在Read/Write deadlock中介绍了这种情况,由于不同的索引访问顺序,更新可能会因读取而死锁。不太可能是您的情况,但由于文档如此糟糕,一切皆有可能。

Many many more deadlock scenarios are possible, but we'd enter esoterics or start to extrapolate quite far for the missing info in the OP.

If I'd venture a guess, the most likely case is 2). The case 1) would probably easily be identifier. Case 2) is a bit harder to detect in simple code analysis because it depnds on the physical schema design (index structure).

于 2010-03-02T00:48:37.773 回答
0

在分析器中运行跟踪(选择空白模板),选择死锁图事件,然后在出现的新选项卡(事件提取设置)上,将每个(检查分别保存死锁 XML 事件)保存在自己的文件中。在 xml 查看器中打开这个文件,很容易知道发生了什么。每个进程都包含在内,还有一堆过程调用等,所有的锁也都在里面,所以你可以确定是什么导致了死锁。

让这个跟踪一直运行到死锁再次发生,信息只在死锁发生时记录,所以开销不大。

于 2010-03-01T22:28:43.327 回答