如何强制使用行锁?

gra*_*l8d 6 sql-server deadlock sql-server-2008-r2 locking isolation-level

我试图让我的表使用行锁。我已经禁用了锁升级。隔离级别为READ_COMMITTED_SNAPSHOT

alter table <TABLE_NAME> SET (LOCK_ESCALATION=DISABLE)
go
alter index <INDEX_NAME> ON <TABLE_NAME> SET (ALLOW_PAGE_LOCKS=OFF) 
go
Run Code Online (Sandbox Code Playgroud)

设置后还是不行。

我是否需要重建我的表以使其不使用页面锁定?

Pau*_*ite 12

禁用页面锁定的设置适用于每个索引,因此将此更改应用于聚集索引只会影响通过该索引访问数据的执行计划。如果表上有非聚集索引,您可能还必须为它们禁用页锁定。以下脚本演示了这一点:

CREATE TABLE dbo.LockTest
(
    col1    integer IDENTITY NOT NULL,
    col2    integer NOT NULL,
    col3    integer NOT NULL,

    CONSTRAINT PK_LockTest
        PRIMARY KEY CLUSTERED (col1)
);
GO
CREATE UNIQUE NONCLUSTERED INDEX UQ_LockTest
ON dbo.LockTest (col2);
GO
ALTER TABLE dbo.LockTest SET (LOCK_ESCALATION=DISABLE);
ALTER INDEX PK_LockTest ON dbo.LockTest SET (ALLOW_PAGE_LOCKS=OFF);
Run Code Online (Sandbox Code Playgroud)

使用聚集索引作为访问方法:

-- Error 651:
-- Cannot use the PAGE granularity hint on the table "dbo.LockTest"
-- because locking at the specified granularity is inhibited.
SELECT col1
FROM dbo.LockTest WITH (INDEX(PK_LockTest), PAGLOCK);
Run Code Online (Sandbox Code Playgroud)

使用非聚集索引:

-- Succeeds: page locks allowed on index UQ_LockTest
SELECT col2 FROM dbo.LockTest AS lt WITH (PAGLOCK);

-- Succeeds: UQ_LockTest also includes col1
-- NC indexes always include the clustering key
SELECT col1 FROM dbo.LockTest AS lt WITH (PAGLOCK);

-- Fails: cannot retrieve col3 without touching the clustered index
SELECT col3 FROM dbo.LockTest AS lt WITH (PAGLOCK);
Run Code Online (Sandbox Code Playgroud)

请注意,禁用页面锁定可能会产生意想不到的副作用,例如阻止索引重组(因为此过程在页面级别工作):

-- Error 1943:
-- The index "PK_LockTest" on table "LockTest" cannot
-- be reorganized because page level locking is disabled.
ALTER INDEX PK_LockTest ON dbo.LockTest REORGANIZE;

-- Succeeds (page locking available):
ALTER INDEX UQ_LockTest ON dbo.LockTest REORGANIZE;
Run Code Online (Sandbox Code Playgroud)