MVCC
MVCC(Multi-Version concurency Control,多版本并发控制 )是一种并发控制机制,允许多个事务同时读取和写入数据库,而无需互相等待,从而提高数据库的并发性能。
首先需要先了解当前读 和快照读两个概念
当前读
读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。对于我们日常的操作,如:select ... lock in share mode(共享锁),select ... for update、update、insert、delete(排他锁)都是一种当前读。
快照读
简单的select(不加锁)就是快照读,快照读,读取的是记录数据的可见版本,有可能是历史数据,不加锁,是非阻塞读。
- Read committed(RC读已提交):每次select,都生成一个快照读。
- Repeatable Read(RR可重复读 ):开启事务后第一个select语句才是快照读的地方。
- Serializable(串行化 ):快照读会退化为当前读。
--
MVCC基本原理
在 MVCC 中,数据库为每个事务创建一个数据快照 。每当数据被修改时,MySQL不会立即覆盖原有数据,而是生成新版本的记录。每个记录都保留了对应的版本号或时间戳。
多版本之间串联起来就形成了一条版本链 ,这样不同时刻启动的事务可以无锁地获得不同版本的数据(普通读)。
此时读(普通读)写操作不会阻塞写操作可以继续写,无非就是会创建新的数据版本(但只有在事务提交后,新版本才会对其他事务可见。未提交的事务修改不会影响其他事务的读取),历史版本记录可供已经启动的事务读取。
--
MVCC主要由:隐藏字段、undo log、readView组成
隐藏字段:
- DB _TRX_ID(事务id),记录每一次操作的事务id,是自增的
- DB_ROLL_PTR(回滚指针),指向上一个版本的事务版本记录地址
- DB_ROW_ID(隐藏主键),如果没有主键,则后会生成该隐藏字段
undo log:
-
回滚日志:存储老版本数据
-
版本链:不同事务或相同事务对同一条记录进行修改,会导致该记录的undo log生成一条记录版本链表,表的头部是最新的旧记录,链表尾部是最早癿撄耧的旧记录。
readView(读视图)
ReadView(读视图)是 快照读 SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃的事务(未提交的)id。
- 根据readView的匹配规则和当前的一些事务id判断该访问那个版本的数据
- 不同的隔离级别快照读是不一样的,最终的访问的结果不一样
- RC:每一次执行快照读时生成ReadView
- RR:仅在事务中第一次执行快照读时生成ReadView,后续复用
ReadView中包含了四个核心字段:
字段 | 含义 |
---|---|
m_ids | 当前活跃的事务ID集合 |
min_trx_id | 最小活跃事务ID |
max_trx_id | 预分配事务ID,当前最大事务ID+1(因为事务ID是自增的) |
creator_trx_id | ReadView创建者的事务ID |