为什么插入语句的独占锁不起作用

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 级锁。