Skip to content

什么是MVCC

MVCC,全称Multi-Version Concurrency Control,即多版本并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。

当前读和快照读

  • 当前读:像select...lock in share mode(共享锁),select...for update;update、insert、delete(排他锁)这些操作都是一种当前读,为什么叫当前读?就是它读取的是记录的最新版本,读取时还是要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。
  • 快照读:像不加锁的select操作就是快照读,即不加锁的非阻塞读,快点找读的前提是隔离级别不是串级别,串行级别下的快照读会退化成当前读,之所以会出现快照读的情况,是基于提高并发性能的考虑,快照读的基于多版本并发控制,即MVCC,可以认为MVCC是行锁的一种变种,但他在多情况下,避免了加锁操作,降低了开销,既然是基于多版本,即快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本

MVCC是为了实现读-写冲突不加锁,而这个读就是快照读,而非当前读,当前读实际上是一种加锁的操作,是悲观锁的实现

MVCC实现原理

隐式字段

每行记录除了我们自定义的字段外,还有数据隐式定义的BD_TRX_ID,DB_ROLL_PTR,DB_ROW_ID等字段

  • DB_TRX_I:6byte,最近修改(修改、插入)事务ID,记录创建这条记录最后一次修改该记录的事务ID
  • DB_ROLL_PTR:7byte,回滚指针,指向这条记录的上一版本(存储于rollback segment里)
  • DB_ROW_ID:6byte,隐含的自增ID(隐藏主键),如果数据表没有主键,InnoDB会自动以DB_ROW_ID产生一个聚簇索引
  • 实际还有一个删除flag隐藏字段,既记录被更新或删除并不代表真的删除,而是删除flag变了

undo日志

  • insert undo log:代表事务在insert新纪录时产生的undo log,只在事务回滚时需要,而且在事务提交后可以立即丢弃
  • update undo log:事务在进行update或者delete时产生undo log,不仅在事务回滚时需要,在快照读时也需要,所以不能随便删除,只有在快速度或者事务回滚不涉及改日志时,对应的日志才会被purge线程统一清除

purge

  • 为了实现InnoDB的MVCC机制,更新或者删除操作都只是设置一个老记录的deleted_bit,并不真正将过时的记录删除
  • purge线程清理deleted_bit为ture的记录。purge线程也维护了一个read view(这个read view相当于系统总最老活跃事务的read view)。如果某个记录的deleted_bit为ture,并且DB_TRX_ID相对于purge线程的read view可见,那么这条记录一定是可以被安全清除的