Mysql的MVCC原理|青训营笔记

78 阅读2分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的第5篇笔记

MVCC

mysql两种读数据的方式:

  1. 当前读 读取记录的最新版本,会对读取的记录加锁,以保证别的并发事务无法修改当前记录。

select ... lock in share mode | 共享锁
select ... for update | 排他锁

  1. 快照读 一般的select语句都是快照读(一种不需要加锁的读)
  • Read Committed : 每次select,都生成一个快照读
  • Repeatable Read : 开启事务后第一个select,开启快照读
  • Serializeable : 全是当前读(加锁)

MVCC(Multi-Version Concurrency Control),多版本并发控制,快照读就是依靠MVCC实现的,其实现主要依赖以下三个方面:

  • 数据库记录的三个隐藏字段;
  • undo log;
  • readView;
  1. 三个隐藏字段 三个隐藏字段分别为最近修改事务ID、回滚指针、隐藏主键
    隐藏主键在当前表没有主键的情况添加,其余两个一定会添加。

  2. undo log

保存了记录的多个版本,并用回滚指针相连。
当insert 的时候,产生的undo log日志只在回滚时需要,在事务提交后,可被立即删除。
当update、delete 的时候,产生的undo log日志不仅在回滚时需要,在快照读时也需要,不会立即被删除。

  1. readView

read View(读视图)是快照读select执行时MVCC提取数据的依据,记录并维护系统当前活跃的事务Id。 其中包含四个核心字段:

m_ids(当前活跃的事务ID集合)
min_trx_id (最小活跃事务ID)
max_trx_id (下一个将要分配的事务ID【即当前最大活跃事务ID + 1】)
createor_trx_id (ReadView创建这本身的事务ID)

如果读到的undo log版本链对应的事务ID(trx_id)满足

  • trx_id == creator_trx_id
  • trx_id < min_trx_id
  • min_trx_id <= trx_id < max_trx_id && trx_id 不属于集合m_ids 这三个条件,那么该条记录就是可读的。

每次进行快照读的时候,会从undo log的版本链中,从上到下进行匹配(尽可能读最新的数据),一旦读到满足上述三个条件的记录,就作为当前的快照读。

  • Read Committed : 每次select生成ReadView
  • Repeatable Read : 开启事务后第一个select,生成ReadView,后面复用。

Read Committed会有不可重复读的并发异常,Repeatable Read不会有。