web-dev-qa-db-ja.com

行ロックの使用を強制する方法は?

テーブルに行ロックを使用させようとしています。ロックのエスカレーションはすでに無効にしています。分離レベルは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

これを設定してもまだ機能しません。

ページロックを使用しないようにするには、テーブルを再構築する必要がありますか?

6
grassbl8d

ページロックを無効にする設定はインデックスごとに適用されるため、この変更をクラスター化インデックスに適用すると、そのインデックスを介してデータにアクセスする実行プランにのみ影響します。テーブルに非クラスター化インデックスがある場合は、それらのページロックも無効にする必要がある場合があります。次のスクリプトはこれを示しています。

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);

アクセス方法としてクラスター化インデックスを使用する:

-- 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);

非クラスター化インデックスの使用:

-- 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);

ページロックを無効にすると、インデックスの再編成を防止するなど、予期しない副作用が生じる可能性があることに注意してください(このプロセスはページレベルで機能するため)。

-- 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;
12
Paul White 9