【问题标题】:SELECT statement is not blocked by an existing exclusive table lockSELECT 语句未被现有的独占表锁阻塞
【发布时间】:2020-11-25 21:43:04
【问题描述】:

为了测试,我试图模拟从我们的 Web 应用程序到我们的 SQL Server 后端的查询会超时的情况。 Web 应用程序已配置,因此如果查询运行时间超过 30 秒,就会发生这种情况。我觉得最简单的方法是在 Web 应用程序要查询的表上获取并持有一个排他锁。据我了解,独占锁应该防止任何额外的锁(甚至是 SELECT 语句采用的共享锁)。

我使用了以下方法:

创建一个长期持有的锁

在 SSMS 中打开第一个查询窗口并运行

BEGIN TRAN; 
    SELECT * FROM MyTable WITH (TABLOCKX); 
    WAITFOR DELAY '00:02:00';
ROLLBACK;

(见https://stackoverflow.com/a/25274225/2824445

确认锁

我可以EXEC sp_lock 并查看 ObjId 匹配 MyTable、TAB 类型、X 模式的结果

试着被锁挡住

在 SSMS 中打开第二个查询窗口并运行 SELECT * FROM MyTable

我希望它会坐下来等待,直到第一个查询释放锁之后才返回任何结果。相反,第二个查询会立即返回完整结果。

我尝试过的东西

  • 在第二个查询窗口中,如果我SET TRANSACTION ISOLATION LEVEL SERIALIZABLE,那么第二个查询会一直等到第一个查询按预期完成。但是,重点是在我们的 Web 应用程序中模拟超时,我没有任何简单的方法可以将 Web 应用程序连接的事务隔离级别更改为远离默认的 READ COMMITTED
  • 在第一个窗口中,我尝试在事务中修改表的值。在这种情况下,当第二个查询立即返回时,它显示的值是未修改的值。

【问题讨论】:

    标签: sql-server


    【解决方案1】:

    想通了。我们打开了 READ_COMMITTED_SNAPSHOT,这就是第二个查询能够在“我试过的东西”的第 2 部分中返回之前未修改的值的方式。我能够通过SELECT is_read_committed_snapshot_on FROM sys.databases WHERE name = 'MyDatabase' 确定这一点。使用ALTER DATABASE MyDatabase SET READ_COMMITTED_SNAPSHOT OFF 关闭它后,我开始看到第二个查询将等待第一个查询完成的预期行为。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-01
      • 2018-09-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多