事务隔离级别的隐式更改如何、何时以及为何发生?

Gen*_*нин 1 sql-server concurrency transaction locking isolation-level

RCSI(读提交快照隔离)是更改 SQL Server 中(默认)读提交隔离级别行为的数据库设置。

据我了解,这是 MSDN 博客文章“并发系列:最小化更新程序之间的阻塞”中的 sripts 的上下文,它告诉我们:

  • “使用 RCSI 的第二个技巧也不起作用,并且更新被行上的 session-1 阻塞在 X 锁后面,(C1 = 1)。原因是以下 UPDATE 语句在比读取提交更高的隔离级别执行。

    update basic_locking set c2 = 1000 where c1 = 2

    这是显示阻塞的输出

    TA 的隐式提升是水平

    解决方案:这里有两个选择来解决这个问题:”

“输出”如何说明隐式默认隔离级别(已提交读)的隐式提升?

如何在某些语句的上下文中检查真正的隔离级别“跳跃”?

什么时候期待它们,它们为什么会发生?

Pau*_*ite 5

输出如何说明隔离级别的隐式提升?

Sunil 在技术上是正确的,但听起来确实有点令人困惑,我同意。

输出显示会话被阻塞,等待获取U锁。READ COMMITTED隔离级别的定义是会话只会遇到提交的数据。SQL Server 在默认的悲观(锁定)实现读取提交下通过保持共享锁足够长的时间来避免看到未提交的数据来满足此逻辑要求。这些共享锁通常会很快释放(通常在读取下一行之前)。

在乐观(行版本控制)读取提交 ( RCSI) 下,SQL Server 通过读取语句开始时最后提交的行版本来避免读取未提交的数据。

Sunil 试图传达的意思是,获取U锁(而不是简短的共享锁或读取版本)代表了隔离级别的(技术)升级(尽管不是任何明确命名的级别)。

这种情况下的有效隔离级别并不完全REPEATABLE READ是因为任何获取的U锁(并且没有转换为X锁)在语句结束时被释放。这与UPDLOCK提示的行为不同,提示获取并持有U锁(至少)直到事务结束。此外,REPEATABLE READ通常获取S锁(尽管这只是一个实现细节)。

令人困惑的是,U识别要在默认(锁定)读提交下更新的行时,引擎还会锁定访问方法。这是一种方便,可以避免常见的死锁场景,而无需UPDLOCK显式指定。我很抱歉这太复杂了,但我们就是这样。

如何在某些语句的上下文中检查真正的隔离级别“跳跃”?

查询计划中没有明确公开任何内容来识别引擎临时增加有效隔离级别的情况。这可能会在 SQL Server 的未来版本中发生变化。可能有关于锁定的间接证据,但这很少是一种方便的方法。

什么时候期待它们,它们为什么会发生?

发生内部升级的某些情况(在某种程度上)记录在联机丛书中。例如,Understanding Row Versioning-Based Isolation Levels说(以及其他值得注意的事情):

在使用行版本控制的读提交事务中,选择要更新的行是使用阻塞扫描完成的,其中在读取数据值时对数据行进行更新 (U) 锁定。

临时更改有效隔离级别更改的一般原因是为了避免数据损坏。列出了一些常见案例的帖子列表如下:

使用预取级联引用完整性阻塞运算符
大对象
查找

其他常见情况(非完整列表):

  • 查询处理器验证外键关系时使用的共享锁。
  • 维护引用多个表的索引视图时采用的范围锁。
  • 使用IGNORE_DUP_KEY.

其中一些行为可能记录在联机丛书中的某处,但我知道没有方便的单一列表。