MVCC(多版本并发控制)

什么是MVCC

  • MVCCC是MySQL InnoDB存储引擎中的一种并发控制机制,通过保存数据的多个版本来管理事务间的并发访问。允许事务在读取数据时不用加锁,读取数据的历史快照,从而减少锁的抢用、提高并发性并且保证事务的隔离性。MVCC解决的问题是在高并发环境下,既要支持多事务并行操作,又要尽量避免因锁导致性能下降。

MVCC的优点和缺点

优点:

  1. 减少锁竞争,提高并发性能;
  2. 在快照读的时候不会阻塞其他事务,支持高效的读操作;
  3. 支持事务的隔离性

缺点:

  1. 需要存储多个版本数据,增加存储开销;
  2. Undo log产生额外的读写和管理开销;
  3. 不及时垃圾回收,会导致性能下降。

MVCC的实现主要依赖以下机制:

  1. 隐藏元信息:每行数据包括两个隐藏字段:
  • 创建版本号:记录事务开始时的唯一ID,表示数据是由哪个事务创建的
  • 删除版本号:表示数据被哪个事务删除,未删除时为空
  1. Undo log:修改数据时,InnoDB会将旧版本数据保存到Undo log,用于回溯。
  2. 事务版本号:事务启动时会分配一个递增ID,用来判断数据的可见性。

MVCC支持哪些隔离级别?

在MySQL中,只有RR和RC两种隔离级别才会使用快照读。

  1. 读已提交(RC):每次查询都会生成一个新的快照,读取最新的已提交数据。
  2. 可重复读(RR):在事务开始生成一致性视图,整个事务期间看到的数据版本一致。
  3. 读未提交不使用MVCC;串行化通过加锁控制,通常不会用到MVCC。

MVCC和锁的区别

  • 锁:直接阻止其他事务访问数据,适合更新频繁、冲突较多的情况,因此性能比较差
  • MVCC:通过快照读实现数据的版本控制,避免加锁操作,更适合高并发场景,需要注意存储和垃圾回收。

在MVCC中,当前读和快照读的区别

  1. 当前读:读取最新数据版本,可能需要加锁来确保读取到的最新数据是一致的。比如:
sql 复制代码
SELECT ... FOR UPDATE、DELETE、UPDATE
  1. 快照读:读取事务启动时的一致性视图,读取历史版本数据,无需加锁。比如普通的SELECT语句。

MVCC是如何与Read View(一致性视图)结合的?

在MySQL中,Read View是MVCC实现快照读的核心。事务在第一次执行快照读的时候,会生成一个Read View,记录当前活跃事务的ID列表。

  • 读取数据时,事务会根据一致性视图判断哪些版本的数据是可见的
  • 在RR隔离级别下,Read View在事务开始时生成,并保持不变
  • 在RC隔离级别下,每次查询都会生成新的视图

假设系统性能出现问题,如何优化MVCC

  1. 减少长事务:避免长时间未提交的事务,避免Undo log堆积
  2. 选择合适的隔离级别:根据业务场景选择RC或RR,减少不必要的回滚开销。
  3. 索引优化:减少回滚链长度,避免大范围扫描Undo log。
  4. 调整垃圾回收策略:合理设置innodb_max_purge_laginnodb_purge_threads,确保Undo log能够及时回收。

如何查看MVCC的Undo log是否存在性能问题?

  1. 查看SHOW ENGINE INNODB STATUS,分析Undo log是否堆积。
  2. 检查innodb_max_purge_lag参数是否合理设置,避免垃圾回收延迟过多。
  3. 检查长事务:长时间未提交的事务会阻止Undo log回收,可以通过INFORMATION_SCHEMA.INNODB_TRX查询正在运行的事务。

MVCC和RR(可重复读)

根据事务的不同隔离级别,Read View的时机是不同的。

  • 在RC隔离级别下,每次select都会获取一次Read view
  • 在RR隔离级别下,只有一个事务中的第一次select才会获取第一次Read view