什么是MVCC
- MVCCC是MySQL InnoDB存储引擎中的一种并发控制机制,通过保存数据的多个版本来管理事务间的并发访问。允许事务在读取数据时不用加锁,读取数据的历史快照,从而减少锁的抢用、提高并发性并且保证事务的隔离性。MVCC解决的问题是在高并发环境下,既要支持多事务并行操作,又要尽量避免因锁导致性能下降。
MVCC的优点和缺点
优点:
- 减少锁竞争,提高并发性能;
- 在快照读的时候不会阻塞其他事务,支持高效的读操作;
- 支持事务的隔离性
缺点:
- 需要存储多个版本数据,增加存储开销;
- Undo log产生额外的读写和管理开销;
- 不及时垃圾回收,会导致性能下降。
MVCC的实现主要依赖以下机制:
- 隐藏元信息:每行数据包括两个隐藏字段:
- 创建版本号:记录事务开始时的唯一ID,表示数据是由哪个事务创建的
- 删除版本号:表示数据被哪个事务删除,未删除时为空
- Undo log:修改数据时,InnoDB会将旧版本数据保存到Undo log,用于回溯。
- 事务版本号:事务启动时会分配一个递增ID,用来判断数据的可见性。
MVCC支持哪些隔离级别?
在MySQL中,只有RR和RC两种隔离级别才会使用快照读。
- 读已提交(RC):每次查询都会生成一个新的快照,读取最新的已提交数据。
- 可重复读(RR):在事务开始生成一致性视图,整个事务期间看到的数据版本一致。
- 读未提交不使用MVCC;串行化通过加锁控制,通常不会用到MVCC。
MVCC和锁的区别
- 锁:直接阻止其他事务访问数据,适合更新频繁、冲突较多的情况,因此性能比较差
- MVCC:通过快照读实现数据的版本控制,避免加锁操作,更适合高并发场景,需要注意存储和垃圾回收。
在MVCC中,当前读和快照读的区别
- 当前读:读取最新数据版本,可能需要加锁来确保读取到的最新数据是一致的。比如:
sql
SELECT ... FOR UPDATE、DELETE、UPDATE
- 快照读:读取事务启动时的一致性视图,读取历史版本数据,无需加锁。比如普通的SELECT语句。
MVCC是如何与Read View(一致性视图)结合的?
在MySQL中,Read View是MVCC实现快照读的核心。事务在第一次执行快照读的时候,会生成一个Read View,记录当前活跃事务的ID列表。
- 读取数据时,事务会根据一致性视图判断哪些版本的数据是可见的
- 在RR隔离级别下,Read View在事务开始时生成,并保持不变
- 在RC隔离级别下,每次查询都会生成新的视图
假设系统性能出现问题,如何优化MVCC
- 减少长事务:避免长时间未提交的事务,避免Undo log堆积
- 选择合适的隔离级别:根据业务场景选择RC或RR,减少不必要的回滚开销。
- 索引优化:减少回滚链长度,避免大范围扫描Undo log。
- 调整垃圾回收策略:合理设置
innodb_max_purge_lag和innodb_purge_threads,确保Undo log能够及时回收。
如何查看MVCC的Undo log是否存在性能问题?
- 查看
SHOW ENGINE INNODB STATUS,分析Undo log是否堆积。 - 检查
innodb_max_purge_lag参数是否合理设置,避免垃圾回收延迟过多。 - 检查长事务:长时间未提交的事务会阻止Undo log回收,可以通过
INFORMATION_SCHEMA.INNODB_TRX查询正在运行的事务。
MVCC和RR(可重复读)
根据事务的不同隔离级别,Read View的时机是不同的。
- 在RC隔离级别下,每次select都会获取一次Read view
- 在RR隔离级别下,只有一个事务中的第一次select才会获取第一次Read view