【问题标题】:Unexpected behaviour of the Serializable isolation level可序列化隔离级别的意外行为
【发布时间】:2020-07-16 21:48:55
【问题描述】:

测试设置

我有一个 SQL Server 2014 和一个简单的表 MyTable,其中包含列 Code (int)Data (nvarchar(50)),没有为此表创建索引。

我在表中有4条记录,方式如下:

1, First
2, Second
3, Third
4, Fourth

然后我在事务中运行以下查询:

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ

BEGIN TRANSACTION

DELETE FROM dbo.MyTable 
WHERE dbo.MyTable.Code = 2

我有一个受影响的行,我没有发出 Commit 或 Rollback。

接下来我开始另一个事务:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

BEGIN TRANSACTION

SELECT TOP 10 Code, Data
  FROM dbo.MyTable
  WHERE Code = 3

在这一步,带有 SELECT 查询的事务挂起,等待带有 DELETE 查询的事务完成。

我的问题

我不明白为什么带有 SELECT 查询的事务正在等待带有 DELETE 查询的事务。据我了解,删除的行(代码 2)与所选行(代码 3)无关,据我了解,隔离级别 SERIALIZABLE SQL Server 在这种情况下不应该锁定整个表。也许发生这种情况是因为 SERIALIZABLE 的最小锁定量是一个页面?然后,如果表有更多行,例如 1000000(其他页面中的某些行不会被锁定),那么它可能会产生从其他页面中选择行的不一致行为。请帮助弄清楚为什么在我的情况下会发生锁定。

【问题讨论】:

    标签: sql sql-server transaction-isolation


    【解决方案1】:

    在锁定 READ COMMITTED、REPEATABLE READ 或 SERIALIZABLE 下,SELECT 查询必须为查询计划实际读取的每一行放置共享 (S) 锁。锁可以放置在行级、页级或表级。此外,SERIALIZABLE 将在范围上放置锁,这样在持有锁时没有其他会话可以插入匹配的行。

    因为您“没有为此表创建索引”,所以这个查询:

    SELECT TOP 10 Code, Data
      FROM dbo.MyTable
      WHERE Code = 3
    

    必须通过表扫描执行,并且必须读取所有行(即使是 Code=2 的行)以确定它们是否符合 SELECT 条件。

    这就是为什么您应该几乎总是使用Row-Versioning 的原因之一,要么将数据库设置为 READ COMMITTED SNAPSHOT,要么将只读事务编码为使用 SNAPSHOT 隔离。

    【讨论】:

    • 我在表的 Code 列上添加了一个聚集唯一索引,并且行为发生了变化;现在执行 SELECT 的事务不会等待使用 DELETE 查询的事务完成。感谢您的快速和合格的答复!
    • 如果这个答案已经解决了您的问题,那么请接受这个答案并投票。
    • @David Browne:使用列 Code 上的聚集索引,我开始一个 SERIALIZABLE 事务,没有提交或回滚,查询 SELECT * FROM MyTable WHERE Code = 6。然后我开始另一个 SERIALIZABLE 事务,查询插入 dbo.MyTable(代码,数据)值(5,“第五”)。第二个事务挂起,等待第一个事务的提交或回滚。您能否另外澄清一下为什么这次我要挂起事务#2(使用插入查询)?这些事务使用完全不同的值与列 Code 上的集群索引一起工作。
    • 让我猜猜,没有 Code=6 的行。在这种情况下,SERIALIZABLE SELECT 的键范围锁定将锁定相邻的键值。 SERIALIZABLE 充满了惊喜。他们中的大多数都很糟糕。
    • @David Browne:再次感谢您!还有另一笔交易;从头开始,行为不再可重现,SERIALIZABLE 隔离级别按预期工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-24
    • 2021-01-14
    • 2023-03-04
    • 2017-10-20
    • 1970-01-01
    • 2012-12-29
    • 2021-06-21
    相关资源
    最近更新 更多