SQL 服务器:Tablock,在 select 之前或之后锁定?
SQL Server : Tablock, locks before or after select?
在下面的示例中,当使用 with (tablockx)
时,锁定是在 select 确定最大值之前完成的,还是之后完成的?是否存在插入语句插入 table "table1" 的竞争条件,或者是否保证 @foo 将包含在 table 中找到的最大值,直到事务被提交或回滚?
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
Is the locking done before the select determines the max value, or
after
之前,在查询优化器执行之前。事后再做也于事无补。这是您正在执行的语句的锁定方法。
Is there a race condition with insert statements inserting into table
"table1"
不,因为您使用的是 TABLOCKX
而不仅仅是 TABLOCK
。后者允许共享锁,但您通过 TABLOCKX
.
获得 table 上的独占锁
Is it guaranteed that @foo will contain the max value found in the
table until the transaction is committed or rolled back
是的,所有其他事务都将被阻止(删除、插入、更新等)
正在测试
要对此进行测试,请创建一个 table 并插入一个值
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 window 中尝试插入一个新值,或者其他任何东西
insert into t1_delete
values(2)
您会注意到查询旋转。如果您在 另一个查询 window 中从 Adam Mechanic 运行 exec sp_whoIsActive
,您可以明白为什么。具体来说,检查插入会话的 blocking_session_id
。这将是与 sql_test
的会话,例如 begin transaction declare @foo....
测试完别忘了提交事务
Tablockx 将获取一个独占锁,该锁在事务提交或回滚时释放。所以你的评论区会被屏蔽
在下面的示例中,当使用 with (tablockx)
时,锁定是在 select 确定最大值之前完成的,还是之后完成的?是否存在插入语句插入 table "table1" 的竞争条件,或者是否保证 @foo 将包含在 table 中找到的最大值,直到事务被提交或回滚?
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
Is the locking done before the select determines the max value, or after
之前,在查询优化器执行之前。事后再做也于事无补。这是您正在执行的语句的锁定方法。
Is there a race condition with insert statements inserting into table "table1"
不,因为您使用的是 TABLOCKX
而不仅仅是 TABLOCK
。后者允许共享锁,但您通过 TABLOCKX
.
Is it guaranteed that @foo will contain the max value found in the table until the transaction is committed or rolled back
是的,所有其他事务都将被阻止(删除、插入、更新等)
正在测试
要对此进行测试,请创建一个 table 并插入一个值
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 window 中尝试插入一个新值,或者其他任何东西
insert into t1_delete
values(2)
您会注意到查询旋转。如果您在 另一个查询 window 中从 Adam Mechanic 运行 exec sp_whoIsActive
,您可以明白为什么。具体来说,检查插入会话的 blocking_session_id
。这将是与 sql_test
的会话,例如 begin transaction declare @foo....
测试完别忘了提交事务
Tablockx 将获取一个独占锁,该锁在事务提交或回滚时释放。所以你的评论区会被屏蔽