SqlServer 2005:没有共享记录的死锁问题

时间:2009-09-17 07:18:32

标签: sql-server-2005 deadlock

我遇到了两个不访问任何常见记录的事务的死锁问题。也没有锁升级。所以我无法解释为什么会出现死锁。

当两个此类事务同时执行时发生死锁:

begin transaction

update A set [value] = [value]
where id = 1; /* resp. 2 */

/* synchronize transactions here */

SELECT * 
FROM  
 A inner join B on A.B_FK = B.id
 inner join C on C.A_FK = A.id
WHERE 
 A.[value] = 1; /* resp. 2 */

rollback;

这些是设置场景的表格和数据:

CREATE TABLE A (
  id INT NOT NULL,
  [value] INT,
  B_FK INT
  primary key (id)
)

CREATE TABLE B (
  id INT NOT NULL,
  primary key (id)
)

CREATE TABLE C (
  id INT NOT NULL,
  A_FK INT
  primary key (id)
)

INSERT INTO A VALUES(1, 1, 1) 
INSERT INTO B VALUES(1) 
INSERT INTO C VALUES(1, 1) 

INSERT INTO A VALUES(2, 2, 2) 
INSERT INTO B VALUES(2) 
INSERT INTO C VALUES(2, 2) 

A位于三个表的中间。如果我在查询中更改了任何内容,例如删除其中一个联接的表BC,则不存在死锁。我按A.id而不是A.value进行过滤时也一样。

死锁图告诉我他们都希望将S锁设置为表A的主键索引。再说一遍:没有锁升级。

我正在使用SqlServer 2005。

  • 为什么这些交易在没有访问任何公共数据时会发生冲突?任何人都可以解释一下吗?
  • 我可以做些什么来避免它?我正在使用NHibernate,无法轻松更改查询。
  • 可能是SqlServer问题吗?

非常感谢。

2 个答案:

答案 0 :(得分:7)

可能会发生冲突,因为SQL-Server不仅会锁定行级别,还会锁定页面甚至表级别。

这意味着即使记录本身并未实际使用,也可以锁定记录,但只能记录“附近”的记录。

SQL Server Lock Contention Tamed可能会有所帮助

答案 1 :(得分:1)

另外,当你有时遇到这些问题时要考虑的另一件事是锁定可能来自触发器完成的处理。