1.MVCC概念
MVCC指的是多版本控制,指的是一种提高并发的技术,在多版本控制中,只有写写之间相互阻塞,其他三种操作都可以并发执行,这样大幅度提高了InnoDB的并发度。在内部实现中,InnoDB通过undo log保存每条数据的多个版本,并能够找回数据历史版本提供给用户读
MYSQL的InnoDB存储引擎默认事务隔离级别是RR(可重复读),是通过“行级锁+MVCC”一起实现的,正常读的时候不加锁,写的时候加锁,而MVCC的实现依赖:隐藏字段、Read View、Undo log
1.1.隐藏字段
InnoDB存储引擎在每行数据后面添加了三个隐藏字段:
- DB_TRX_ID:表示对本记录行作修改(insert| update| delete)的事务ID
- DB_ROLL_PTR:回滚指针,指向当前记录行的undo log信息
- DB_ROW_ID:这个字段主要用于当表没有主键或唯一非空索引,InnoDB就会使用这个行ID自动产生聚簇索引,如果表中有主键或唯一非空索引时,聚簇索引就不会包含这个行ID了
1.2.Read View
Read View其实跟快照是一个概念,Read View主要是用来做可见性判断的,里面保存了“对本事务不可见的其他活跃事务”,在InnoDB中,创建一个新事物后,执行第一个select语句时(且该select语句不加锁),InnoDB会创建一个快照(Read View),快照中会保存系统当前不应该被本十五看到的其他活跃事务id列表(即trx_ids),Read View保存了几个变量:
- low_limit_id:目前出现过的最大事务ID+1,即下一个将被分配的事务ID
- up_limit_id:活跃事务列表trx_ids中最小的事务ID
1.3 Undo log
Undo log中存储的是老版本数据,当一个事务需要读取记录行时,如果当前记录行不可见,可以顺着undo log链找到满足其可见性条件的记录行版本,undo log可以分为两类:
- insert undo log:事务对insert新纪录时产生的undo log,只在事务回滚时需要,并且在事务提交后就可以立即被丢弃
- update undo log:事务对记录进行delete和update操作时产生的undo log,不仅在事务回滚时需要,快照读页需要,只有当数据库所使用的快照中不涉及该日志记录时,对应的回滚日志才会被purge线程删除
2.记录行修改的具体流程
当事务A对某行记录进行修改时,步骤如下:
- 事务A先对该行加排他锁
- 然后把该行数据拷贝到undo log中,作为旧版本
- 拷贝完毕,对该行数据做出修改,将修改后的最新数据写入到redo log,然后将回滚指针指向拷贝到undo log的旧版本
- 事务提交,释放排它锁