SQL Server:设置这些索引选项的效果

Phi*_*ler 6 index sql-server-2008 sql-server

一个重新索引脚本最近在我们的开发环境,集运行ALLOW_ROW_LOCK = FALSEALLOW_PAGE_LOCKS = FALSE数据库中的所有索引。

这是在测试新的重新索引脚本时完成的 - 这不是故意完成的。

运行此脚本后,我们立即开始看到大量我们通常从未见过的死锁。

  1. 在索引上设置锁定选项是直接原因吗?
  2. 为什么这些设置会导致死锁?

Jon*_*gel 6

评论中链接的文章说得很清楚,但让我们用一个例子来证明它。

CREATE TABLE t1(a int);
INSERT INTO t1(a) VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9);

CREATE CLUSTERED INDEX IX_t1
    ON t1(a)
        WITH(ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON); /* Default */


BEGIN TRANSACTION;

    UPDATE t1
        SET a = 10
        WHERE a = 1;

    EXEC sp_lock;

ROLLBACK;

DROP TABLE t1;
Run Code Online (Sandbox Code Playgroud)

结果(过滤到 SPID 和感兴趣的表):

spid dbid ObjId IndId 类型资源模式状态
52 6 213575799 1 PAG 1:118 IX 赠款
52 6 213575799 1 钥匙 (de42f79bc795) X 赠款
52 6 213575799 1 钥匙 (241332e1ddb0) X 赠款
52 6 213575799 0 TAB IX 赠款 <--
52 6 0 0 DB S GRANT

(有两个KEY锁,因为 SQL Server 需要同时保护“before”和“after”索引值。如果你想看到这个,SELECT a, %%lockres%% FROM t1UPDATE语句之前和之后运行。)

如果我使用具有ALLOW_ROW_LOCKS = OFF和的聚集索引定义再次运行相同的脚本ALLOW_PAGE_LOCKS = OFF,我会得到:

spid dbid ObjId IndId 类型资源模式状态
52 6 0 0 DB S GRANT
52 6 229575856 0 TAB X GRANT <--

所以现在你为什么突然开始陷入僵局应该很明显了!