学习InnoDB:MVCC

121 阅读3分钟

MVCC(多版本并发控制)

是数据库系统中的一种并发控制技术,用于解决多个事务同时读写数据时的并发问题。其核心思想是通过为每个事务提供一个数据的“快照”版本来避免加锁,从而实现高并发下的读写操作,同时保证数据的一致性。

MySQL的InnoDB存储引擎下RC、RR且快照读下基于MVCC做数据的多版本并发控制

当前读和快照读

  • 当前读:读取的数据是最新版本,读取数据时还要保证其他并发事务不会修改当前的数据,当前读会对读取的记录加锁

select ... lock in share mode(共享锁); select ... for update | insert | delete (排 他锁)

  • 快照读: 每一次修改数据都会在undo log 中存有快照记录,就是读取undo log中的某一版本的快照,优点是无须加锁,缺点是读取到的数据可能不是最新的版本

select ...

MVCC实现原理

  1. 隐藏字段

row_id 当数据库表没定义主键时,InnoDB会以row_id为主键生成一个聚簇索引

trx_id 操作这条记录的事务id

rollpointer 回滚指针,通过回滚指针连起来实现undolog版本链

  1. undo版本链

  1. readview

隐藏字段和undo版本链决定了返回的数据,具体返回哪个版本由readview + 版本链访问规则/可见性算法决定

readview:

1. <font style="background-color:#FBDE28;">m_ids</font> 当前活跃的事务id集合 
2. <font style="background-color:#FBDE28;">max_trx_id </font> 最大事务id(+1)  生成ReadView时系统应该分配给下一个事务的id
3. <font style="background-color:#FBDE28;">min_trx_id </font>m_ids中最小事务id
4. <font style="background-color:#FBDE28;">creator_trx_id</font> readview创建者事务id

版本链访问规则:

MVCC在RC、RR下的不同表现

RC:每次都是读取最新的readview(另一个线程修改数据,当前事务能够感知到)

RR:读取的事务开始时的readview

同事务内,RC可能两次快照读返回的是不用版本的记录

而RR则两次快照读返回的是相同版本

解释了为什么RC有不可重复读问题,RR是可重复读

MVCC解决了什么问题

MVCC在快照读解决了幻读现象,这也是为什么说Innodb很大程度上解决了幻读

update、delete等当前读用的间隙锁和临键锁给数据上锁,别的事务就写不了了

当两个都是快照读或两个都是当前读情况下,幻读确实被解决了,但是当一个是快照读另一个是当前读的情况下幻读依然存在,比如一个事务里先select再insert,select得到的是经过MVCC限制过版本的数据而非最新数据,但insert读取的数据是最新的数据,此时这个数据可能已经被其它事务修改了,这就导致了幻读