SQL Server:Tablock,在选择之前还是之后锁定?

时间:2018-11-09 16:42:42

标签: sql-server sql-server-2008-r2

在下面的示例中,当使用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

2 个答案:

答案 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将获取排他锁,该排他锁在提交事务或回滚事务时释放。因此,您的评论区域将被屏蔽。