【问题标题】:Difference between (TABLOCKX) and (TABLOCKX, HOLDLOCK)(TABLOCKX) 和 (TABLOCKX, HOLDLOCK) 的区别
【发布时间】:2021-11-11 00:13:13
【问题描述】:

使用 (TABLOCKX) 和同时使用 (TABLOCKX, HOLDLOCK) 提示有什么区别? 在事务提交之前,似乎表被一个 TABLOCKX 独占锁定,(TABLOCKX,HOLDLOCK)有什么好处?

例如,

BEGIN TRANSACTION SELECT TOP 1 * FROM Foo WITH (TABLOCKX)...
vs
BEGIN TRANSACTION SELECT TOP 1 * FROM Foo WITH (TABLOCKX, HOLDLOCK)...

【问题讨论】:

  • 这能回答你的问题吗? TABLOCK vs TABLOCKX
  • TABLOCKX 在表上获得一个排他锁,防止其他任何锁被占用。使用HOLDLOCK 会导致该锁一直保留到事务结束,而不是直到使用完该表。
  • @Jayasurya Satheesh,我已经对其进行了审查,但它比较了其他提示。我的问题是 (TABLOCKX, HOLDLOCK) 与单 (TABLOCKX) 有什么好处

标签: sql sql-server tsql


【解决方案1】:

TABLOCKX 更改记录范围和对表采取的锁定类型,将所有锁定提升到表范围并使其独占(即不与其他会话共享)。

另一方面,HOLDLOCK 将当前隔离级别提升为可序列化,有效地将锁的时间范围从“只要我在此事务中使用此表”更改为“直到这笔交易结束,即使我不再使用它”。

所以 (TABLOCKX) 和 (TABLOCKX, HOLDLOCK) 之间的区别在于,来自 TABLOCKX 的表范围的独占锁现在一直保持到事务结束,即使您的事务不再使用表。如果没有 HOLDLOCK,这些锁只会在您实际使用表时在事务中保持。

请注意,单独的 TABLOCK(X) 不会在使用后保持锁定,如引用 from the doc 所示:

标签 指定在表上应用获取的锁 等级。获取的锁类型取决于语句 被执行。例如,一个 SELECT 语句可能会获取一个共享的 锁。通过指定TABLOCK,共享锁应用于整个 表而不是行或页级别。如果 HOLDLOCK 也是 指定时,表锁将一直保持到事务结束。

TABLOCKX 只是带有排他锁的 TABLOCK:

TABLOCKX 指定对表进行排他锁。


显然,我上面写的不正确。根据@DavidBrowne-Microsoft 的说法,“X 锁和 U 锁(至少在因为锁定提示而被占用时)始终保持到事务结束。”。这令人困惑,因为 Hints 上的文档页面从未明确表示(或否认)这一点(尽管可能有其他一些 MS 文档页面这样做)。

所以(TABLOCKX)(TABLOCKX,HOLDLOCK) 有效地做同样的事情。我认为有些人这样做是因为和我一样,他们对 Hints 上的文档感到困惑。

【讨论】:

  • 感谢您的输入,但我的问题不是比较 TABLOCKX 与 HOLDLOCK。我已经用示例更新了帖子以澄清问题。
  • @supervisor 我认为我的回答确实解决了这个问题,但我会明确说明......好吧,我已经更新了。这能回答你的问题吗?
  • @supervisor 让我们从另一个角度尝试一下:您从哪里读到 TABLOCKX 持有锁直到事务结束?我知道没有任何 Microsoft 文档这样说或暗示这一点。
  • X 锁和 U 锁(至少在因为锁提示而被占用时)始终保持到事务结束。 SERIALIZABLE/HOLDLOCK 也触发范围锁定,但如果您已经有一个表级 X 锁,这并不重要。 S 锁和 U 锁通常会尽快释放,除非隔离级别要求持有它们。
  • 可能是因为不是每个人都知道TABLOCKX会一直持有到交易结束,所以两者同时使用让意图变得超级清晰。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多