我已经看到在组合中使用与UPDLOCK的HOLDLOCK暗示的许多例子( 这样 )。 但是微软的文档 ,这些提示使它看起来像HOLDLOCK应该是多余的,因为UPDLOCK已经持续了锁,直到事务结束。 (此外,它似乎是说,HOLDLOCK仅适用于共享锁呢。)
如何HOLDLOCK影响查询,如果在所有?
我已经看到在组合中使用与UPDLOCK的HOLDLOCK暗示的许多例子( 这样 )。 但是微软的文档 ,这些提示使它看起来像HOLDLOCK应该是多余的,因为UPDLOCK已经持续了锁,直到事务结束。 (此外,它似乎是说,HOLDLOCK仅适用于共享锁呢。)
如何HOLDLOCK影响查询,如果在所有?
它有一个很大的影响。
更新锁发生在该行的更新锁,网页和表格/数据库的共享锁。意向更新。
这不会从表中访问数据停止其他疑问,因为页/数据库上的锁是纯粹的共享锁。 他们可能只是因为试图执行将违背锁的操作交锋对个人行/页/表锁。 如果发生该请求将队列中的当前锁的背后,等待它来使用它可以再继续。
通过使用HOLDLOCK,查询被强制进行序列化,专门锁定表,直到动作完成。 这将防止有人读取表,除非使用NOLOCK提示,允许潜在脏读。
要看到效果,产生的示例表“富”,并把一些垃圾数据吧。
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(所有企业) - 所有安装在几乎默认设置,使用所有默认设置的测试数据库中创建(刚进入只有DB的名称)。
安德鲁的回答的是正确的按照MSDN文档,但是我反对2008R2和2012年的测试,我没有看到这种行为,所以请自己测试
我看到的行为如下:
首先播放的数据库上运行此。
CREATE TABLE [dbo].[foo](
[tableid] [int] IDENTITY(1,1) NOT NULL,
[Col2] [varchar](100) NOT NULL,
CONSTRAINT [PK_foo] PRIMARY KEY CLUSTERED
(
[tableid] ASC
)
)
...并把几排英寸
现在,将此代码粘贴到两个查询标签(改变标签两个“标签中选择一个”文本):
begin tran
select * from foo with (UPDLOCK, HOLDLOCK)
where tableid = 1
UPDATE foo SET Col2 = 'tab one'
where tableid = 1
commit tran
并把这个在另一个选项卡3:
select * from foo
where tableid = 1
确保你在你的游戏数据库指着其中的表。
高亮显示选项卡1 之前的所有更新语句并执行。
不要在标签2相同,你会发现选项卡将不能完成,目前仍在执行。
现在在我的环境里完成执行简单的SELECT在标签3。
高亮显示选项卡1更新语句,并执行它(不做承诺还),你会看到选项卡仍在执行。
来吧和执行选项卡1提交... 标签2现在将完成选择...你可以运行休息。