【问题标题】:drawbacks of disabling lock escalation禁用锁升级的缺点
【发布时间】:2016-10-10 14:18:25
【问题描述】:

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

Create table MyFactTable
(
RunID int,
Key2 int,
Key3 int,
Key4 int,
….
Value2 numeric,
Value3 numeric,
Value4 numeric,
….
)

它还有:

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

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

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

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

ALTER TABLE MyFactTable  SET (LOCK_ESCALATION=DISABLE)

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

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

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

我想值得一提的是,该表永远不会更新,并且一旦插入 RunID,它只会被查询(因此不再使用相同的 RunID 插入),最终会被清理过程删除。

谢谢, 迭戈

【问题讨论】:

  • 它带有资源成本。锁升级的整个过程就是把多条记录锁所需的资源节省下来,全部增加到一个表锁。

标签: sql sql-server locking sql-server-2014


【解决方案1】:

总结:

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

通常插入不会锁定表格,除非您正在执行 bulk loadinginsert select ..

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

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

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

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

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

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

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

【讨论】:

  • 嘿,在我的情况下,它确实是一个“插入...选择”...关于您对一致性的评论,不会对表格进行更新,并且只会在工作后进行删除完成插入。感谢您的回答
  • @Diego:我没有看到任何问题,除了提到的资源使用情况。会做更多的测试并更新答案
猜你喜欢
  • 1970-01-01
  • 2013-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-11
  • 2014-03-13
  • 2023-03-06
  • 1970-01-01
相关资源
最近更新 更多