我在SQL Server中的表,它是CRUD-ED同时在不同的会话同时运行一个存储过程:
|----------------|---------|
| <some columns> | JobGUID |
|----------------|---------|
该过程如下:
- 生成一个GUID。
- 插入一些记录到共享表。如上所述,与来自步骤1中的GUID将它们标记。
- 步骤2执行上的所有记录一些更新。
- 从步骤3作为SP输出选择的记录。
每一个选择/插入/更新/存储过程删除语句具有WHERE JobGUID = @jobGUID
条款,所以程序仅适用于已插在步骤2中。然而记录,有时在同一个存储过程中并行运行在不同的连接,发生在共享表死锁。 下面是从SQL Server Profiler中的死锁图形:
锁升级不会发生。 我尝试添加(UPDLOCK, ROWLOCK)
锁提示所有DML语句和/或包装过程的主体在交易中使用不同的隔离级别,但它并没有帮助。 仍然在共享的表相同的RID锁。
在那之后,我发现共享表没有主键/标识列。 而一旦我说了,死锁似乎消失了:
alter table <SharedTable> add ID int not null identity(1, 1) primary key clustered
当我删除主键列,死锁回来了。 当我添加回去,我不能再重现僵局。
所以,问题是,是一个主键标识列真正能够解决死锁或者是它只是一个巧合吗?
更新:作为@Catcall建议,我已经尝试创建现有列的自然聚集主键(无添加标识列),但还是抓住了相同的僵局(当然,这一次是一键锁定,而不是RID锁)。