重新认识 SI 隔离级别

date
Jul 12, 2023
slug
Understanding_SI_Isolation_Levels
status
Published
tags
Database
事务
summary
本文介绍了快照隔离级别的概念、特点、优缺点以及存在的问题,包括丢失更新、写倾斜和幻读。同时还介绍了实现可串行化的三种方法:字面意义上的串行执行、两阶段锁和可串行化快照隔离(SSI)。
type
Post

缘起

在确定 DuckDB 的可以达到的隔离级别到底对应 MYSQL 的什么隔离级别上和小伙伴有不同的见解
这是在 discord 上询问作者的截图 :)
notion image
notion image
我认为是单独的快照级别,为什么这么说呢,因为 Andy 在他的 slides 单独拿了出来
notion image
小伙伴认为没有这个级别或者说是可重复读于是就展开的一波复习
其实 MySQL 中的可重复读就是快照技术的具体实现,而且每个 DB 对于这个说法使用的名字也不尽相同,可以参考一下 TiDB 是怎么定义他家的快照隔离级别。

问题

  • 怎么理解快照隔离级别?
  • 快照隔离能解决幻读吗?存在什么问题?
  • 什么是写倾斜?举个例子
  • 快照隔离能保证串行化吗?如果要实现串行化怎么做?

快照隔离的概念

Conceptually, snapshot isolation involves giving a transaction a “snapshot” of the database at the time when it begins its execution. It then operates on that snapshot in complete isolation from concurrent transactions. The data values in the snapshot consist only of values written by committed transactions. This isolation is ideal for
read-only transactions since they never wait and are never aborted by the concurrency manager.
从概念上讲,快照隔离为事务在开始执行时提供了一个数据库的“快照”。然后,它在与并发事务完全隔离的情况下对该快照进行操作。快照中的数据值仅包括已提交事务写入的值。这种隔离对于只读事务非常理想,因为它们从不等待,并且永远不会被并发管理器中止。

快照隔离的特点

  • 采用MVCC+2PL的混合模式。
  • 对写操作加排它锁。
  • 读操作不加锁,而是访问某个时间点的历史版本。
  • PostgreSQL 和 MySQL 称其快照隔离级别为可重复读(repeatable read)

快照隔离的优缺点

  1. 优点 ◦ 读写互不干扰。 ◦ 读事务在不阻塞更新事务的情况下执行。
  1. 缺点 ◦ 不能保证可串行化 ◦ 存在写倾斜问题 ◦ 存在丢失更新

各种隔离级别存在的问题

  1. 丢失更新 lost update 两个客户端同时执行 读取 - 修改 - 写入序列。其中一个写操作,在没有合并另一个写入变更情况下,直接覆盖了另一个写操作的结果。所以导致数据丢失。快照隔离的一些实现可以自动防止这种异常,而另一些实现则需要手动锁定(SELECT FOR UPDATE)。
  1. 写倾斜 write skew 一个事务读取一些东西,根据它所看到的值作出决定,并将该决定写入数据库。但是,写入时,该决定的前提不再是真实的。只有可串行化的隔离才能防止这种异常。写倾斜异常:是指两个事务(T1和T2)并发读取一个数据集(例如包含V1和V2),然后各自利用读到的信息修改数据集中不相交的数据项(例如T1修改V1,T2修改V2),最后并发提交事务。——《云原生数据库》
  1. 幻读
MySQL的MVCC+Next-Key lock并不能完全解决幻读问题
事务读取符合某些搜索条件的对象。另一个客户端进行写入,影响搜索结果。快照隔离可以防止直接的幻像读取,但是写入偏差上下文中的幻读需要特殊处理,例如索引范围锁定。 select * from tb where id > 100; // 结果为0 insert into tb values(101); commit select * from tb where id > 100; // 结果为1

快照隔离不可串行化的情况

notion image
  • 如果按照串行化执行,最终的结果要么是AA,要么是BB,而不会存在如图所示的BA。

实现可串行化的三种方法

  1. 字面意义上的串行执行
    1. 如果每个事务的执行速度非常快,并且事务吞吐量足够低,足以在单个 CPU 核上处理,这是一个简单而有效的选择。
  1.  两阶段锁
    1. 数十年来,两阶段锁定一直是实现可串行化的标准方式,但是许多应用出于性能问题的考虑避免使用它。
  1. 可串行化快照隔离(SSI) 一个相当新的算法,避免了先前方法的大部分缺点。它使用乐观的方法,允许事务执行而无需阻塞。当一个事务想要提交时,它会进行检查,如果执行不可串行化,事务就会被中止。

结论

SI 事实上是个广义的概念,实现 SI 的基本技术是 MVCC,所以可以狭义的理解,SI ≈ RR。

参考文档

  • 《数据库系统概念》第七版 18.8 快照隔离

© Phoenix Z 2021 - 2025