(TABLOCKX)和(TABLOCKX, HOLDLOCK)之间的区别

3
使用 (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 - Jayasurya Satheesh
2
TABLOCKX 对表格进行独占锁定,防止其他锁定被获取。使用 HOLDLOCK 会导致该锁定一直保持到事务结束,而不仅仅是在该表格使用完毕后。 - paneerakbari
@Jayasurya Satheesh,我已经审查过了,但它与其他提示进行了比较。我的问题是(TABLOCKX,HOLDLOCK)相对于单个(TABLOCKX)有什么好处? - supervisor
1个回答

6

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

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

因此,(TABLOCKX)和(TABLOCKX,HOLDLOCK)之间的区别在于,来自TABLOCKX的全表独占锁现在将保持到事务结束,即使您的事务不再使用表格。没有HOLDLOCK,这些锁将仅在您实际使用表格时在事务中保持。

请注意,仅使用TABLOCK(X)将不会保持锁超过其使用,如此引述来自文档

TABLOCK指定获取的锁应用于表级别。所获取的锁类型取决于正在执行的语句。例如,SELECT语句可能会获取共享锁。通过指定TABLOCK,共享锁将应用于整个表而不是行或页级别。如果还指定了HOLDLOCK,则表锁将保持到事务结束。TABLOCKX只是具有排他锁的TABLOCK。
显然,我上面写的是错误的。根据@DavidBrowne-Microsoft所说,"无论何时由于锁提示而获取的X锁和U锁都会一直保留到事务结束。"。这很令人困惑,因为Hints文档页面从未明确说明(或否认)这一点(尽管可能有其他MS文档页面这样做)。因此,实际上(TABLOCKX)(TABLOCKX,HOLDLOCK)的作用相同。我认为有些人这样做是因为像我一样被提示文档搞糊涂了。

@supervisor 我认为我的回答确实回答了那个问题,但我会明确一下...好的,我已经更新了。这样是否回答了您的问题? - RBarryYoung
1
@supervisor 让我们从另一个角度来尝试:你在哪里读到 TABLOCKX 会一直持有锁,直到事务结束?我不知道微软的文档中有这样的说法或暗示。 - RBarryYoung
3
X锁和U锁(至少是因为锁提示而被获取的)始终保持到事务结束。SERIALIZABLE/HOLDLOCK也会触发范围锁定,但如果您已经具有表级别的X锁,则这不会产生影响。 S锁和U锁通常会尽快释放,除非隔离级别要求它们保持锁定状态。 - David Browne - Microsoft
1
可能是因为不是每个人都知道TABLOCKX将会一直持有到事务结束,所以使用两者可以使意图非常清晰。 - David Browne - Microsoft
在 UPDATE 过程中扫描时获取的 U 锁将被释放。因 UPDLOCK 提示而获取的 U 锁将会保持。 - David Browne - Microsoft
显示剩余14条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接