我们知道,MySQL的四种隔离级别,Innodb引擎默认隔离级别是RR(可重复读),解决了不可重复读的问题,但是原理是什么呢?即MVCC (多版本并发控制)
首先需要了解以下几点:
隐藏字段
MySQL的表中存在隐藏字段:
1、trx_id(事务id):记录每一次操作事务的id,自增
2、roll_pointer(回滚指针):指向上一个事务版本记录地址
undolog
1、回滚日志,存储老版本数据
2、版本链:多个事务并行操作某一行记录,记录不同事务修改数据的版本,通过roll_pointer指针形成一个链表。
ReadView
ReadView (读视图)是快照读 SQL执行时MVCC提供数据的依据,记录并维系着系统当前的活跃事务(未提交的)id
- 当前读:读取的时记录的最新版本,读取时要保证其他并发事务不能修改当前记录,会对读取的数据进行加锁,对于我们日常的操作如:select ...lock in share mode (共享锁)、 select ...for update 、update、insert、delete (排他锁)都是当前读
- 快照读:简单的select不加锁,就是快照读,读取的时记录数据的可见版本,有可能是历史数据,不加锁,是非阻塞读
ReadView包含四个核心字段:
字段 | 含义 |
m_ids | 当前活跃的事务id集合 |
min_trx_id | 最小活跃事务id |
max_trx_id | 预分配事务id,当前最大事务id+1 |
creator_trx_id | ReadView创建者的事务ID |
ReadView的生成时机不同,就是RC(读已提交 )和RR(可重复读 )的关键所在!
RC:每一次执行快照读时生成ReadView
RR:仅在事务第一次执行快照读时生成ReadView,后续复用,这样就保证,同一个事务的多次读取都是同一个readView,保证了可重复读