【问题标题】:SQL Server Isolation Levels - Repeatable ReadSQL Server 隔离级别 - 可重复读取
【发布时间】:2009-11-04 18:30:29
【问题描述】:

我无法弄清楚为什么会发生这种情况。很确定我理解这个理论,但肯定有其他我看不到的事情发生。

表 A 具有以下架构:

ID [Primary Key]
Name
Type [Foreign Key]

SprocA 将隔离级别设置为可重复读取,并从表 A 中选择具有Type=1 的行。它还会更新这些行。

SprocB 从表 A 中选择具有Type=2 的行。

现在鉴于这些是完全不同的行集,如果我同时执行这两个行(并调用 WAITFOR 以减慢它的速度),SprocB 直到 SprocA 才会完成。

我知道这与对 Type 的查询有关,就好像我根据 Primary ID 进行选择一样,它允许并发访问表。

有人解释了吗?

干杯

【问题讨论】:

  • 您确定在 SprocA 和 SprocB 执行期间没有执行任何数据库修改(即使是触发器)?
  • 是的,绝对确定没有触发器。
  • 执行更新需要多长时间?此外,是否涉及事务——通过 BEGIN TRANSACTION/COMMIT 或通过某些应用程序连接设置? (被 SET IMPLICIT_TRANSACTIONS 的流氓设置转移了好几天......)

标签: sql-server isolation-level


【解决方案1】:

为隔离级别设置可重复读取后,您将对读取的所有数据持有共享锁,直到事务完成。直到你 COMMIT 或 ROLLBACK。

这将降低您的应用程序访问这些数据的并发性。因此,如果您的第一个过程 SELECTS from table 然后调用 WAITFOR 然后 SELECTS 在事务中再次等,您将一直持有共享锁,直到您提交事务或过程完成。

如果这是您正在使用的测试过程,请尝试在每次选择后添加一个 COMMIT,看看这是否有助于第二个过程同时运行。

祝你好运!

凯文

【讨论】:

  • 那很好,但我没有看到的问题是为什么 SprocB 在读取 SprocA 未触及的行时会出现问题?
  • 数据库通常提供不同类型的锁定方案,可以在数据库设置中进行配置。除了锁定整个表的表锁之外,您还有行级锁定,我认为您假设这里发生了,而数据页级锁定锁定了 X 行的数据页。例如,X 可能是 10 行,具体取决于数据页的大小等。但是如果您锁定的是数据页而不是单行,那么另一个过程可能会尝试访问锁定数据页中的行。这些帮助有用?干杯凯文
  • 抱歉,刚刚看到您对来自存储过程 A 的以下更新的评论。然后我会假设该锁已通过更新从共享锁提升为排他锁。因此,如果它是一个数据页而不是被锁定的行,那么您可能会锁定 X 行而不是您正在处理的单行。
【解决方案2】:

SQL Server 使用索引来执行范围锁(这是可重复读取经常使用的),因此如果您没有 Type 索引,它可能会锁定整个表...

【讨论】:

  • 抱歉,我忘记了重要信息 - SprocA 将更新这些行。
【解决方案3】:

要记住的是,锁定的行对于其他进程来说是黑盒子。

您知道 SprocA 只是读取 type = 1 的数据,而 SprocbB 只是读取 type = 2 的数据。

但是,SprocB 不知道 SprocA 将对这些记录做什么。在事务完成之前,SprocA 可能会将所有记录更新为 type = 2。在这种情况下,如果 SprocB 不等待 SprocA 完成,它将无法正常工作。

在执行范围锁定/批量更改时保持并发性很困难。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-14
    • 1970-01-01
    • 2020-04-04
    • 2021-01-27
    • 1970-01-01
    • 1970-01-01
    • 2011-12-10
    相关资源
    最近更新 更多