禁用锁升级的缺点

Die*_*ego 5 sql sql-server locking sql-server-2014

我有一个名为 MyFactTable 的表,如下所示:

Create table MyFactTable
(
RunID int,
Key2 int,
Key3 int,
Key4 int,
….
Value2 numeric,
Value3 numeric,
Value4 numeric,
….
)
Run Code Online (Sandbox Code Playgroud)

它也有:

  • RunID 上的非唯一聚集索引(非唯一,因为 RunID 可以有数十万行与之关联);
  • 一些其他的非聚集索引来帮助查询;

运行 ID 彼此完全隔离,通常我会将多个进程插入到此表中(显然具有不同的运行 ID)。问题是我似乎无法并行运行插入,这意味着当进程 A 插入表时,进程 B 也被阻止这样做。

在 95% 的情况下,这不是什么大问题,因为大多数 RunID 非常小(少于 50 万行),它们只会锁定表几秒钟,但最终会产生更大的工作(20+ 百万行) ) 启动并锁定表几分钟,阻止所有较小的进程完成。

我想这是因为第一个尝试插入表的进程正在获取一个表锁,所以我用这个命令禁用了锁升级:

ALTER TABLE MyFactTable  SET (LOCK_ESCALATION=DISABLE)
Run Code Online (Sandbox Code Playgroud)

那确实解决了问题,但现在我想知道这样做的后果是什么。

有没有人遇到过这样的情况并愿意分享他们的经验。

其次,我可以采用哪些其他可能的解决方案?我想过对表进行分区并将所有小运行放在一个分区中,将所有大运行放在另一个分区中(我不在乎大的是否阻塞自己,我只是想确保小的不会被大的)。你怎么看?

我想值得一提的是,这个表永远不会更新,一旦插入了 RunID,它只会被查询(因此不会再插入具有相同 RunID 的内容),最终它会被清理过程删除。

谢谢,迭戈

The*_*war 4

概括:

对于插入/选择,除了某些资源使用之外,我没有看到禁用锁升级的任何问题

通常插入不会锁定表,除非你正在做bulk loadinginsert select..

当您禁用锁升级时,除了使用更多内存之外,我没有看到插入有任何问题,除了更多内存使用之外,使用的内存将是

SQLServer中锁使用96字节内存,因此当表为每一行持有行锁时,所使用的内存与行数*96字节成正比

现在讨论当 Lock_escalation 禁用时其他事务的事务一致性,例如同一个表上的插入、更新/删除。

不会有事务不一致,因为如果锁不兼容,它们只会被阻止

最后,我发现其他 DML 事务的性能问题。有关更多详细信息,请参阅下面的示例

Table1 有 1000 页,每页有 100 行,总共 100000 行。现在当您向该表中插入数据时。现在每一行都将被锁定为“X”锁,直到事务完成。因此删除/更新必须检查每个row 知道它是否可以持有锁。之前,它可以检查更高级别的锁

我不确定删除/更新是否会在第一次发现具有不兼容锁的行时立即被阻止,或者它将继续检查,因为 ii 目前没有测试 2008 实例进行测试。将发布更多详细信息