我遇到了两个不访问任何常见记录的事务的死锁问题。也没有锁升级。所以我无法解释为什么会出现死锁。
当两个此类事务同时执行时发生死锁:
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
位于三个表的中间。如果我在查询中更改了任何内容,例如删除其中一个联接的表B
或C
,则不存在死锁。我按A.id
而不是A.value
进行过滤时也一样。
死锁图告诉我他们都希望将S锁设置为表A
的主键索引。再说一遍:没有锁升级。
我正在使用SqlServer 2005。
非常感谢。
答案 0 :(得分:7)
可能会发生冲突,因为SQL-Server不仅会锁定行级别,还会锁定页面甚至表级别。
这意味着即使记录本身并未实际使用,也可以锁定记录,但只能记录“附近”的记录。
答案 1 :(得分:1)
另外,当你有时遇到这些问题时要考虑的另一件事是锁定可能来自触发器完成的处理。