12

我目前在 SQL Server 2008 中遇到与特定用户表频繁死锁的问题。以下是有关此特定表的一些事实:

  1. 有大量的行(1 到 200 万)
  2. 此表上使用的所有索引仅在其选项中勾选 “使用行锁”编辑:表上只有一个索引是其主键
  3. 行经常被多个事务更新,但是是唯一的(例如,可能每小时对不同的唯一行执行一千个或更多更新语句)
  4. 该表不使用分区。

在检查表后sys.tables,我发现lock_escalation设置为TABLE

我很想将此表的 lock_escalation 转换为,DISABLE但我不确定这会产生什么副作用。据我了解,使用DISABLE将最大限度地减少从级别升级锁TABLE,如果与索引的行锁设置结合使用,理论上应该最大限度地减少我遇到的死锁。

从我在确定锁升级阈值中读到的内容看来,当单个事务获取 5000 行时,锁似乎会自动升级。

从这个意义上说,单笔交易意味着什么?通过单独的更新/选择语句获得 5000 行的单个会话/连接?

或者它是获取 5000 行或更多行的单个 sql 更新/选择语句?

任何见解都值得赞赏,顺便说一句,n00b DBA 这里

谢谢

4

2 回答 2

9

LOCK Escalation 在语句对 SINGLE 对象持有超过 5000 个锁时触发。在同一张表的两个不同索引上分别持有 3000 个锁的语句不会触发升级。

当尝试锁升级并且对象上存在冲突锁时,尝试中止并在另外 1250 个锁(持有,未获取)后重试

因此,如果您的更新是在单个行上执行的并且您在列上有一个支持索引,那么锁升级不是您的问题。

您将能够使用来自分析器的 Locks-> lock escalation 事件来验证这一点。

我建议您捕获死锁跟踪以确定死锁的实际原因。

于 2012-12-19T06:24:45.973 回答
1

在快速谷歌禁用表锁升级后,我找到了这篇文章。尽管对于 OP 来说不是一个真正的答案,但我认为它仍然与一次性脚本相关,并且在这里值得注意。您可以使用一个不错的小技巧来临时禁用表锁升级。
打开另一个连接并发出类似的问题。

BEGIN TRAN
SELECT * FROM mytable (UPDLOCK, HOLDLOCK) WHERE 1=0
WAITFOR DELAY '1:00:00'
COMMIT TRAN

作为

如果不同的 SPID 当前持有不兼容的表锁,则不会发生锁升级。

来自微软 kb

于 2015-07-08T13:48:44.310 回答