为什么插入语句的独占锁不起作用
why exclusive lock of insert statement doesn't work
假设有两个事务依次执行:
交易 1:
BEGIN TRANSACTION
INSERT INTO my_table values(1, 'First')
--not committed
交易 2:
BEGIN TRANSACTION
INSERT INTO my_table values(1, 'First')
COMMIT TRANSACTION
为什么事务2允许获取排他锁完成查询,而不是挂起?
因为你问题中例子中的独占锁很可能会被连续占用。
仅 IX
锁定层次结构中的较高对象,例如页面和对象。
这不会阻止事务插入不同的行,因为 IX
锁是 not mutually exclusive。
以下面的table为例
CREATE TABLE my_table
(
X INT,
Y VARCHAR(100)
)
并使用 DBCC TRACEON(1200, -1, 3604)
查看它的锁定信息 returns
Process 57 acquiring IX lock on OBJECT: 7:48719226:0 (class
bit2000000 ref1) result: OK
Process 57 acquiring IX lock on PAGE: 7:1:296 (class bit2000000 ref0)
result: OK
Process 57 acquiring X lock on RID: 7:1:296:5 (class bit2000000 ref0)
result: OK
如果您要创建一个 table 如下禁用行锁(不推荐),您很可能会遇到阻塞,因为 X
锁是在页面级别获取的。
CREATE TABLE my_table
(
X INT,
Y VARCHAR(100)
)
CREATE CLUSTERED INDEX IX on my_table(X) with(ALLOW_ROW_LOCKS = OFF)
在这里,如果插入的记录都不是小的,那么将对行进行锁定。但是这个数字很大,那么 SQL 服务器可能会将行级锁升级到 table 级锁。
假设有两个事务依次执行:
交易 1:
BEGIN TRANSACTION
INSERT INTO my_table values(1, 'First')
--not committed
交易 2:
BEGIN TRANSACTION
INSERT INTO my_table values(1, 'First')
COMMIT TRANSACTION
为什么事务2允许获取排他锁完成查询,而不是挂起?
因为你问题中例子中的独占锁很可能会被连续占用。
仅 IX
锁定层次结构中的较高对象,例如页面和对象。
这不会阻止事务插入不同的行,因为 IX
锁是 not mutually exclusive。
以下面的table为例
CREATE TABLE my_table
(
X INT,
Y VARCHAR(100)
)
并使用 DBCC TRACEON(1200, -1, 3604)
查看它的锁定信息 returns
Process 57 acquiring IX lock on OBJECT: 7:48719226:0 (class bit2000000 ref1) result: OK
Process 57 acquiring IX lock on PAGE: 7:1:296 (class bit2000000 ref0) result: OK
Process 57 acquiring X lock on RID: 7:1:296:5 (class bit2000000 ref0) result: OK
如果您要创建一个 table 如下禁用行锁(不推荐),您很可能会遇到阻塞,因为 X
锁是在页面级别获取的。
CREATE TABLE my_table
(
X INT,
Y VARCHAR(100)
)
CREATE CLUSTERED INDEX IX on my_table(X) with(ALLOW_ROW_LOCKS = OFF)
在这里,如果插入的记录都不是小的,那么将对行进行锁定。但是这个数字很大,那么 SQL 服务器可能会将行级锁升级到 table 级锁。