我遇到两个不访问任何公共记录的事务的死锁问题。也没有锁升级。所以我无法解释为什么可能出现僵局。
当两个这样的事务同时执行时就会发生死锁:
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)
Table A
位于三张桌子的中间。如果我更改查询中的任何内容,例如删除其中一个连接表B
or C
,不存在僵局。当我过滤时也是如此A.id
代替A.value
.
死锁图告诉我他们都想给表的主键索引设置一个S锁A
。再次强调:不存在锁升级。
我正在使用 SqlServer 2005。
- 为什么这些事务在没有访问任何公共数据的情况下会发生冲突?谁能解释一下吗?
- 我可以做什么来避免它?我正在使用 NHibernate,无法轻松更改查询。
- 会不会是SqlServer的问题?
多谢。
这种冲突可能会发生,因为 SQL-Server 不仅在行级别上锁定,而且还在页甚至表级别上锁定。
这意味着即使记录本身并未实际使用,而只是“附近”的不同记录,也可以锁定该记录。
SQL Server 锁争用已被驯服 http://www.sql-server-performance.com/2000/lock-contention-nolock-rowlock/可能会有帮助
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)