首页 > 解决方案 > SQL Server:Tablock,在选择之前还是之后锁定?

问题描述

在下面的示例中,使用时with (tablockx)锁定是在选择确定最大值之前完成还是之后完成?插入到表“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

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

解决方案


锁定是在选择确定最大值之前完成还是之后完成

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

插入语句插入表“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)

您会注意到查询旋转。如果您在另一个查询窗口exec sp_whoIsActive中从Adam Mechanic运行,您可以了解原因。具体来说,请查看您的插入会话。这将是像begin transaction declare @foo...这样的会话。blocking_session_idsql_test

测试后不要忘记提交事务


推荐阅读