MVCC数据库多版本并发控制
参考:微信公众号——Java随想录(全网最详细MVCC讲解,一篇看懂)
MVCC解读
MVCC介绍
MVCC是数据库一种不加锁来解决读写冲突的方案,可以提高数据库并发性能,更好地处理读写冲突。
相较于传统锁机制
传统锁机制也可以解决读写冲突,但使用锁同时也会带来死锁或者阻塞的风险。
MVCC的优势
- 读写操作不会冲突,这极大地提高了数据库的并发性能
- 降低死锁风险
MVCC原理
MVCC机制的核心在于三点:隐藏字段、Undo Log、Read View
隐藏字段
Mysql的行数据除了我们自定义的数据,另外还有一部分隐藏的数据字段
字段 | 含义 |
---|---|
DB_ROW_ID | 作为行数据的隐藏主键,如果表中没有设定主键字段,那InnoDB会默认产生该字段,并选择为隐藏主键 |
DB_TRX_ID | 当先行数据所属的事务ID,事务ID是唯一的 |
DB_ROLL_PTR | 回滚指针,指向的是每个数据的上一个版本 |
Undo Log
Undo log里存放的是反操作,比如执行insert操作,则会在日志中记录delete,然后每条记录都与创建它的事务相关联,能够依次知道该回滚哪个事务的操作。
作用
- 事务回滚:当事务中断或者取消时,InnoDB会利用Undo日志中的记录,还原数据
- MVCC实现:利用Undo日志,InnoDB可以为每个事务提供独立的视图。
回滚步骤
- 进行更新删除操作时,Mysql会将旧数据存入undo log
- 然后利用DB_ROLL_PTR找到旧的log记录
- 将旧值更新到相应行,实现回滚
Read View
InnoDB利用read view来控制事务可以看到哪一版本的数据,这样可以实现每个事务看到的数据都是自己应该看到的,不会受到其他事物影响,即不会发生脏读,幻读,不可重复读。
可见性原则
在开启事务时,Mysql会将要修改数据的DB_TRX_ID取出,并和Undo log中的DB_TRX_ID进行比较,如果不符合规则,则通过DB_ROLL_PTR继续往更早的版本找,直到找到符合的版本。
简单来说,就是找到当前事务最晚可见的版本,这个版本可以是自己当前事务修改的版本,也可以是在当前事务开始前就已经提交的事务版本
Read View维护字段
字段 | 含义 |
---|---|
m_ids | 记录在当前事务开始时,其他未提交事务的id,被称为活跃事务列表 |
m_creator_trx_id | 创建该视图是事务id |
m_low_limit_id | 目前出现的最大事务ID + 1,也就是下一个事务的ID(对创建该视图的时间来说),如果有事务ID大于此值,则说明有事务是在此视图之后创建的,那么它修改的版本,当前视图是范围跟不到的 |
m_up_limit_id | 活跃事务列表中的最小值,如果某个事务ID小于该值,说明该事务已提交,也就可以被视图访问 |
判断规则
- 访问的数据版本的事务号 DB_TRX_ID如果等于创建该视图的事务号m_creator_trx_id,则说明是同一事务做出的修改,可以正常访问
- 访问版本的事务号小于当前记录的最小活跃ID m_up_limit_id,说明在访问已提交数据,自然可以访问
- 如果访问的事务号要大于当前的最大事务号m_low_limit_id,就说明该数据是在视图之后的事务创建的,自然无法访问。
- 如果事务号在m_up_limit_id和m_low_limit_id之间,则需要另外判断该事务是否在活跃表中,如果在,说明是其他事务的修改,本事务无法访问。如果不在,说明创建本视图时,该事务已经提交了,则可以访问。
RC和RR中Read View区别
RC(读提交):每次select都会生成新的read view,这就可能导致不可重复读
RR(可重复读):只会在第一次select生成readview,其余select复用第一次的,保证数据一致。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 驴の奇思妙想!
评论