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

Sql server SQL Server:Tablock,在选择之前还是之后锁定?,sql-server,sql-server-2008-r2,Sql Server,Sql Server 2008 R2,在下面的示例中,当将与(tablockx)一起使用时,锁定是在select确定最大值之前还是之后完成的?是否存在将insert语句插入表“table1”的竞争条件,或者是否保证@foo将包含在表中找到的最大值,直到提交或回滚事务 begin Transaction declare @foo int = (select max(col1) from table1 with (tablockx)) -- Is it possible that max(col1) can be > @foo

在下面的示例中,当将
与(tablockx)
一起使用时,锁定是在select确定最大值之前还是之后完成的?是否存在将insert语句插入表“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
如果重要的话,我使用的是SQLServer2008R2

锁定是否在选择确定最大值之前完成,或 之后

在执行之前,由查询优化器执行。毕竟,这样做也无济于事。这是您正在执行的语句的锁定方法

在表中插入insert语句时是否存在竞争条件 “表1”

不,因为您使用的是
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)
您将注意到查询旋转。如果在另一个查询窗口中运行
exec sp\u whoIsActive
,您可以看到原因。具体来说,请查看插入会话的
阻塞会话\u id
。这将是一个与
sql\u test
类似begintransaction declare@foo….的会话


不要忘记在测试后提交事务

Tablockx将获取一个独占锁,该锁在提交或回滚事务时释放。因此,您的评论区域将被阻止。

我知道它抓住了一个锁,只是不确定它是在确定select将返回哪些行之前还是之后。我认为逻辑上必须在执行查询之前,但我想确定一下。