【问题标题】:SQL Server : Tablock, locks before or after select?SQL Server:Tablock,在选择之前还是之后锁定?
【发布时间】:2018-11-09 16:42:41
【问题描述】:

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


    【解决方案1】:

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

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

    插入语句插入表中是否存在竞争条件 “表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)
    

    您会注意到查询旋转。如果您在另一个查询窗口中从Adam Mechanic 运行exec sp_whoIsActive,您就会明白为什么。具体来说,请查看您的插入会话的 blocking_session_id。这将是与sql_test 的会话,例如开始事务声明@foo...。

    测试后别忘了提交事务

    【讨论】:

      【解决方案2】:

      Tablockx 将获取一个在事务提交或回滚时释放的独占锁。所以你的评论区会被屏蔽。

      【讨论】:

      • 我知道它抓住了一个锁,只是不确定它是在它确定 select 将返回哪些行之前还是之后。我认为它在逻辑上必须在查询执行之前,但我想确定。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-27
      • 1970-01-01
      • 2012-06-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多