sql-server - HOLDLOCK 对 UPDLOCK 有什么影响?

标签 sql-server tsql locking

我见过许多 HOLDLOCK 提示与 UPDLOCK ( like this ) 结合使用的示例。然而Microsoft's documentation这些提示使得 HOLDLOCK 看起来应该是多余的,因为 UPDLOCK 已经将锁保留到事务结束。 (而且似乎 HOLDLOCK 只适用于共享锁。)

HOLDLOCK 对查询有何影响(如果有的话)?

最佳答案

影响很大。

更新锁需要行上的更新锁、页面上的意图更新以及表/数据库上的共享锁。

这不会阻止其他查询访问表中的数据,因为页面/数据库上的锁纯粹是共享锁。他们只是可能不会通过尝试执行与锁相矛盾的操作来与单个行/页/表发生冲突。如果发生这种情况,请求将在当前锁后面排队并等待它可用,然后才能继续。

通过使用holdlock,查询将被强制序列化,以独占方式锁定表,直到操作完成。这可以防止任何人读取该表,除非使用 nolock 提示,从而允许潜在的脏读。

要查看效果,请生成一个示例表“foo”并在其中放入一些垃圾数据。

begin tran

select * from foo with (updlock)
where tableid = 1
-- notice there is no commit tran

打开另一个窗口并尝试:

select * from foo

行返回,现在提交原始查询事务。重新运行它并更改为使用 Holdlock:

begin tran

select * from foo with (updlock, holdlock)
where tableid = 1

返回到另一个窗口并尝试再次选择数据,查询将不会返回值,因为它被排他锁阻塞。在第一个窗口上提交事务,第二个查询的结果将出现,因为它不再被阻止。

最后的测试是使用nolock,使用updlock和holdlock再次运行事务。然后在第二个窗口中运行以下命令:

select * from foo (nolock)

结果会自动返回,因为您已经接受了脏读(读未提交)的风险。

因此,它会产生很大的影响,因为您强制对该表执行的操作被序列化,这可能是您想要的(取决于正在进行的更新),或者会在该表上创建一个非常大的瓶颈。如果每个人都对具有长时间运行事务的繁忙表执行此操作,那么它将导致应用程序内出现严重延迟。

与所有 SQL 功能一样,如果使用正确,它们会非常强大,但错误使用功能/提示可能会导致严重问题。当我必须覆盖引擎时,我更喜欢使用提示作为最后的手段 - 而不是默认方法。

按要求编辑:在 SQL 2005、2008、2008R2(所有企业)中测试 - 全部安装在几乎默认设置上,使用所有默认设置创建测试数据库(仅输入数据库名称)。

关于sql-server - HOLDLOCK 对 UPDLOCK 有什么影响?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1524155/

相关文章:

c# - 为什么我会收到此错误?

sql-server - 以 CHARINDEX 作为长度参数的 T-SQL SUBSTRING

sql - NOLOCK 和 UNCOMMITTED 之间有什么区别

sql-server - 在 mysqldump 中指定日期格式

sql - 优化更新查询

sql-server - 将大量数据从一列传输到另一列的最有效方式?

tsql - CentOS 6.7 和 Windows MSSQL 连接 - FreeTDS 和 PHP

xcode - 我如何在 Xcode StoryBoard 中像 Photoshops 一样使用 'Lock Selection'

android - 我可以为当前线程锁定 SQLite 表吗?

sql - 如何在 WHERE 子句中进行区分大小写的搜索(我使用的是 SQL Server)?