选择基于行版本控制的隔离级别

基于行版本控制的隔离级别通过消除读取操作的锁来改善读取并发。Microsoft SQL Server 引入了两个使用行版本控制的事务隔离级别:

  • READ_COMMITTED_SNAPSHOT 数据库选项为 ON 时,启用使用行版本控制的已提交读隔离的新实现。

  • ALLOW_SNAPSHOT_ISOLATION 数据库选项为 ON 时,启用的新的快照隔离级别。

对于大多数应用程序,建议应用使用行版本控制的已提交读隔离,而不要应用快照隔离,原因如下:

  • 已提交读隔离比快照隔离占用的 tempdb 空间少。

  • 已提交读隔离可用于分布式事务,而快照隔离不能用于分布式事务。

  • 已提交读隔离可用于大多数现有应用程序,而不需要进行任何更改。可以动态优化使用默认隔离级别(已提交读)编写的应用程序。已提交读的行为(是否使用行版本控制)是由数据库选项设置确定的,可以对其进行更改,而不会影响应用程序。

    注意注意

    对于设计为依赖于已提交读隔离的阻塞行为的应用程序,开发人员可能希望将应用程序更改为使用两种模式的已提交读隔离。否则,请注意将 READ_COMMITTED_SNAPSHOT 数据库选项保持为 OFF。

  • 快照隔离很容易发生不适用于使用行版本控制的已提交读隔离的更新冲突。当在快照隔离下运行的事务读取另一个事务稍后会修改的数据时,快照事务对同一数据的更新会导致更新冲突,该事务将终止并回滚。而使用行版本控制的已提交读隔离不存在此问题。

何时应用使用行版本控制的已提交读隔离

使用行版本控制的已提交读隔离提供语句级读取的一致性。事务中的每条语句执行时,新的数据快照将产生,并在该语句执行完成之前对每条语句保持一致。发生下列情况时,启用使用行版本控制的已提交读隔离:

  • 当并发好处大于创建和管理行版本所增加的开销时,将发生读取器/编写器阻塞。

  • 应用程序需要长时间运行的聚合或查询(其中数据值必须与查询启动时的时点一致)绝对精确。

何时使用快照隔离

快照隔离提供事务级读取的一致性。数据快照在快照事务启动时产生并在事务持续时间内保持一致。发生下列情况时,使用快照隔离:

  • 需要开放式并发控制。

  • 由于更新冲突必须回滚事务的可能性较低。

  • 应用程序需要基于必须具有时点一致性的长时间运行的多语句查询生成报告。快照隔离具有可重复读取的优点(请参阅并发影响),而不使用共享锁。数据库快照可以提供类似的功能,但必须手动实现。快照隔离自动为每个快照隔离事务提供数据库中的最新信息。

基于行版本控制的隔离级别的优点

使用行版本控制的隔离级别具有以下优点:

  • 读取操作检索一致的数据库快照。

  • SELECT 语句不会在读取操作期间锁定数据(读取器不会阻止编写器,编写器也不会阻止读取器)。

  • SELECT 语句可以访问最后提交的行值,同时其他事务更新该行,而不会受到阻塞。

  • 死锁的数量减少。

  • 事务所需的锁的数量减少,这减少了管理锁所需的系统开销。

  • 锁升级的次数减少。

基于行版本控制的隔离级别的开销

确定使用基于行版本控制的隔离需要对比最小化锁定的并发好处与维护和读取行版本所需增加的资源使用量。考虑下列与启用用于快照和已提交读隔离级别的行版本控制关联的开销:

  • 当查询所需的版本变旧且必须扫描长版本链时,会影响读取性能。

  • tempdb 中维护行版本时,行版本控制会增加修改数据过程中的资源使用量。

  • 当 READ_COMMITTED_SNAPSHOT 或 ALLOW_SNAPSHOT_ISOLATION 数据库选项为 ON 时,更新和删除特定数据库的事务必须维护行版本,即使不存在使用基于行版本控制的隔离级别的事务。构造使用行版本的一致的数据快照包括系统资源(CPU 和内存),并可能生成 I/O 活动。由于记录版本存储在 tempdb 中,因此当更多的 tempdb 页可以存储在行版本控制的内存中时,性能会更好,发出的 I/O 数也会更少。

    注意注意

    通常,插入行不会生成行版本。但是,在某些情况下,INSERT 命令确实可以生成行版本。例如,如果在前一个删除的行版本(虚影记录)尚未截断时将行插入具有唯一索引的表中,则 INSERT 命令将生成行版本。

  • tempdb 必须具有足够的磁盘空间用于版本存储区。如果存在超长时间运行的事务,则更新事务在该时间内生成的所有版本都必须保留在 tempdb 中。如果 tempdb 运行空间不足,更新操作并不会失败,但使用行版本控制的读取操作可能会失败。

  • 行版本控制信息需要将 14 个字节添加到数据库行。

  • 由于维护行版本的工作,更新性能可能较低。在典型的 OLTP 工作负荷中,每个更新仅更改数据库中的一部分行。在这些系统中,与两个选项都为 OFF 的数据库相比,在选项为 ON 的数据库中更新的性能可能只低几个百分点。当在更新操作过程中更改更大量的数据时,版本更新的性能开销可能变高。

  • 数据读取器遍历版本链接列表时会引起其他开销。快照越旧,在快照隔离事务中访问快照的进程就越慢。

  • 由于更新操作的必需的冲突检测,某些使用快照隔离的更新事务可能必须回滚。在使用行版本控制的已提交读隔离下运行的事务不会生成更新冲突。

使用行版本控制的事务还有其他限制。有关详细信息,请参阅使用基于行版本控制的隔离级别

从基于行版本控制的隔离级别获益的系统

从基于行版本控制的隔离级别获益的方案包括:

  • 并行运行只读报告和即席查询以及更新数据的应用程序的系统。

  • 从支持类似隔离级别的其他关系数据库系统到 Microsoft SQL Server 数据库引擎的应用程序迁移。

  • 获取一致聚合(如 AVG、COUNT 和 SUM)或执行索引交叉和索引联接将需要一个严格的隔离级别(如可重复读或可序列化)的系统。

  • 具有由于读/写争用导致的大量死锁的系统。