当前读和快照读

10 分钟阅读 764 字 + 637 词
注意区分快照读和当前读。
当前读指的是select for update或者select lock in share mode,insert,update, 指的是在更新之前必须先查寻当前的值,因此叫当前读。
快照读指的是在语句执行之前或者在事务开始的时候会创建一个视图( read_view ),后面的读都是基于这个视图的, 不会再去查询最新的值。

在 MySQL 中,InnoDB 存储引擎是支持事务的,并且实现了多版本并发控制(MVCC),这使得它能够支持两种主要的读操作: 快照读 (Snapshot Read)和 当前读 (Current Read)。
快照读
快照读 是指读取操作在不加锁的情况下获取数据的一致视图。这通常用于实现可重复读(Repeatable Read)和读已提交(Read Committed)隔离级别下的读操作。
  • 特征
    • 数据来自于事务开始时或查询开始时的一致快照。
    • 不会阻塞其他事务的写操作,不会被其他事务的写锁所阻塞。
    • 实现了 MVCC,通过读取数据的快照来实现一致性。
  • 典型操作
    • SELECT * FROM table 这样的查询在默认情况下会使用快照读,以保证性能和一致性。
  • 隔离级别
    • 在可重复读和读已提交隔离级别下,普通的 SELECT 查询会使用快照读。
    • 在可重复读(Repeatable Read)下,事务内的所有快照读看到的是事务开始时的快照。
    • 在读已提交(Read Committed)下,事务内的每个快照读看到的是执行时的最新已提交版本。
当前读
当前读 则是指读取操作在获取数据时需要加锁,以便获取当前的最新数据版本。这通常用于需要修改数据或确保读取和写入之间没有并发冲突的操作。
  • 特征
    • 读取的是最新的数据版本,并且会对读取的数据加锁。
    • 阻塞其他事务的写操作,并且可能被其他事务的写锁阻塞。
    • 常用于需要一致性读写的场景。
  • 典型操作
    • SELECT ... LOCK IN SHARE MODE :读取数据并加共享锁。
    • SELECT ... FOR UPDATE :读取数据并加排他锁。
    • INSERT , UPDATE , DELETE :这些操作在执行过程中会进行当前读以根据最新数据版本进行修改。
  • 隔离级别
    • 在所有事务隔离级别下,如果查询需要修改数据(即 DML 操作),则通常使用当前读。
    • 在可串行化(Serializable)隔离级别下,所有的读操作实际上都是当前读,因为它们都需要确保事务之间没有并发冲突。
选择使用
  • 快照读 适用于大多数只读查询,以提高并发性和性能,而不需要考虑事务间的锁冲突。
  • 当前读 则在需要确保查询和后续修改的一致性时使用,或者在需要锁定资源以避免冲突的用例中,例如实现乐观锁和悲观锁机制。
选择使用哪种读方式,取决于具体的业务需求、事务隔离级别以及性能和一致性的权衡。