美文网首页
InnoDB学习笔记(1)MVCC

InnoDB学习笔记(1)MVCC

作者: Sarahhhh | 来源:发表于2019-03-30 19:20 被阅读0次

MySQL · 引擎特性 · InnoDB MVCC 相关实现

InnoDB的多版本并不是直接存储多个版本的数据,而是所有更改操作利用行锁做并发控制,这样对某一行的更新操作是串行化的,然后用Undo log记录串行化的结果。当快照读的时候,利用Undo log重建需要读取版本的数据,从而实现读写并发。

  • 基于Undo log,通过回滚段来构建需要的版本记录
  • 通过ReadView来判断哪些版本的数据可见
  • Purge线程通过ReadView来清理旧版本数据

Undo log

  • 用来做事务的回滚操作,保证事务的原子性
  • 用来构建数据修改之前的版本,支持多版本读

聚集索引的一些额外字段

  • DELETED BIT(1 bit):标识记录是否被删除,聚簇索引和二级索引都有这个标记位。真正的删除在事务commit之后且没有读会引用该版本数据的时候
  • DB_TRX_ID(6 bytes):表示最近一次插入或者更新该记录的事务ID
  • DB_ROLL_PTR(7 bytes):指向该记录的rollback segment的undo log记录
  • DB_ROW_ID(6 bytes):当有新数据插入的时候会自动递增。当表上没有用户主键的时候,InnoDB会自动产生聚集索引,包含DB_ROW_ID字段

更新时

  • 对于聚集索引:原记录位置更新(in-place),由DB_ROLL_PTR指向undo log上的旧记录
  • 对于二级索引:将原记录标记为删除,再插入新的数据记录

当快照读通过二级索引读取数据发现deleted标识或者更新的时候,如果二级索引页上无法判断可见性,InnoDB会查看聚簇索引上的记录行,通过行上的DB_TRX_ID判断可见性,找到正确的可见版本数据

当用mvcc读取的时候(row_search_mvcc),对于聚簇索引,当拿到一条记录后,会先通过函数lock_clust_rec_cons_read_sees判断可见性,如果不可见会再构建老版本数据row_vers_build_for_consistent_read
对于二级索引,拿到记录会先调用lock_sec_rec_cons_read_sees判断page上记录的最近一次修改trx id是否小于m_up_limit_id,如果小于即该page上数据可见,否则即调用row_search_idx_cond_check检查可见性,对于ICP,索引条件下推的,可以先判断索引条件是否满足条件,这样避免不满足条件的行回表;对于满足条件的行则回表查看可见性。

由于在修改聚集索引记录时,总是存储了回滚段指针和事务id,可以通过该指针找到对应的undo 记录,通过事务Id来判断记录的可见性。当旧版本记录中的事务id对当前事务而言是不可见时,则继续向前构建,直到找到一个可见的记录或者到达版本链尾部。

在Undo log中会记录TRX_UNDO_TRX_ID事务ID和TRX_UNDO_TRX_NO事务Commit时的number值。当事务为读写事务的时候,事务会获取trx_id。当事务commit时会获取新的系统trx id作为trx_no。
Undo log会保留直到事务提交同时没有其他快照读引用后才会purge。所以需要尽量避免长语句或长事务的执行,避免因此导致的undo堆积或者undo链太长使读取变慢。

相关文章

网友评论

      本文标题:InnoDB学习笔记(1)MVCC

      本文链接:https://www.haomeiwen.com/subject/hcvsbqtx.html