在下面的示例中,当使用with (tablockx)
时,是在select确定最大值之前还是之后进行锁定?在插入语句插入表“ table1”中时是否存在竞争条件,还是可以保证@foo将包含表中找到的最大值,直到事务被提交或回滚?
begin Transaction
declare @foo int = (select max(col1) from table1 with (tablockx))
-- Is it possible that max(col1) can be > @foo here?
Commit Transaction
如果有关系,我正在使用SQL Server 2008 R2
答案 0 :(得分:2)
在选择确定最大值之前是否已完成锁定,或者 之后
之前,由查询优化器执行之前。毕竟,这样做无济于事。这是您正在执行的语句的锁定方法。
是否存在带有插入语句插入表的竞争条件 “ table1”
否,因为您使用的是TABLOCKX
,而不仅仅是TABLOCK
。后者允许共享锁,但是您可以通过TABLOCKX
在表上获得排他锁。
是否保证@foo将包含在 表,直到事务被提交或回滚
是的,所有其他交易将被阻止(删除,插入,更新等)
测试
要对此进行测试,请创建一个表并插入一个值
create table t1_delete (col1 int)
insert into t1_delete
values (1)
go
接下来,在一个SSMS面板中运行您的代码,但注释掉COMMIT TRAN
begin Transaction
declare @foo int = (select max(col1) from t1_delete with (tablockx))
-- Is it possible that max(col1) can be > @foo here?
select @foo
--Commit Transaction
现在,在新的SSMS窗口中尝试插入新值或其他任何值
insert into t1_delete
values(2)
您会注意到查询旋转。您可以在另一个查询窗口中查看为什么从Adam Mechanic运行exec sp_whoIsActive
。具体来说,请检出blocking_session_id
用于插入会话。这将是与sql_test
的会话,例如开始交易声明@foo ... 。
别忘了在测试后提交交易
答案 1 :(得分:2)
Tablockx将获取排他锁,该排他锁在提交事务或回滚事务时释放。因此,您的评论区域将被屏蔽。