【问题标题】:TABLOCKX not workingTABLOCKX 不工作
【发布时间】:2016-03-13 19:43:47
【问题描述】:

我正在使用我的 SQL Server 2012 试图获得锁。根据我看到的教程,我尝试测试获取表上的排他锁,以便没有其他查询能够从中读取信息,直到事务没有结束,但它只是不工作。即使它在视频中工作,这是我在第一个窗口中的查询:

use TSQL2012

BEGIN transaction

update tele with (TABLOCKX, holdlock) 
set cor = '12'

waitfor delay '00:05'
go

然后在第二个查询窗口中我只是尝试了:

select * from tele

它工作得很好,尽管理论上应该有“排他”锁来防止这种情况。为什么会这样?我也试过了

set transaction isolation level serializable on

也没有延迟,但选择总是成功的。有什么想法吗?

【问题讨论】:

  • 无法重现 - 在我的情况下,在 UPDATE 之后和提交/回滚该事务之前,SELECT 在该表上被 阻塞(如预计)
  • 你打开Snapshot Isolation了吗?
  • @VladimirBaranov 没关系,他正在使用 SERIALIZABLE。
  • 关闭为无法重现(目前),因为重现行为的条件未知。

标签: sql-server sql-server-2012 table-lock


【解决方案1】:

我已经在两个不同的表上进行了尝试,并且可以轻松地重现您发现的内容。这是正在发生的事情:

如果 Sql-Server 在更新表之前将行返回给 SELECT 查询,那么很可能此时您的 Tele 表上已经存在与排他锁不兼容的锁。例如,如果某个地方的另一个会话已经在表上拥有了读取器锁,那么您的 UPDATE 语句将被挂起,WAIT_TYPE 为 LCK_M_X,这意味着您的 UPDATE 被阻塞,等待与排他锁不兼容的锁释放。由于所有锁都与独占表锁不兼容,因此当任何其他会话使用任何类型的锁访问表时,您的更新语句将被挂起。

在第三个 SQL Management Studio 实例中,右键单击您的服务器并打开活动监视器。过滤您的数据库并登录并重新运行实验。如果表是应用程序经常使用的表,并且 SELECT 在 UPDATE 之前运行,那么您会注意到 UPDATE 上的 LCK_M_X WAIT_TYPE。

尝试创建一个只有您知道的新表,然后重新运行实验。它应该工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-30
    • 2021-01-10
    • 1970-01-01
    相关资源
    最近更新 更多