1.概念
mvcc( muti version concurrency control), 多版本并发控制 , RC和RR隔离级别是基于mvcc机制 ,数据库中的某条记录同时具有多个版本,在事务进行操作中时根据事务id以及隔离级别去判断读取哪个版本. mvcc实现了读写并发,相较于加锁,整体效率得到提升.
2.涉及知识点
2.1 undolog & 版本链
当对一条数据进行修改时,会生成一个与修改相反的日志以便进行数据还原, 即undo log
每次修改都会记录undolog 节点的指针, 多个版本通过回滚指针链接在一起,形成一个链表,即版本链
undolog 主要用于:
- 事务回滚
- 快照读
2.2 隐式字段
每条数据都有3个隐式字段
row_id: 当数据记录无主键时会使用row_id代替主键
trx_id: 最新事务id
roll_pointer: 回滚指针,指向undolog
2.3 快照读&当前读
快照读: 读取数据的可见版本, 不加锁
当前读: 读取数据的当前版本(最新), 加锁
select * from t lock in share mode; //共享读锁
select * from t for update; //写锁
2.4 read view
事务中执行sql语句则会开启一个read view (RC级别下,每个sql开启一个readview, RR级别下,每个事务开启一个readview) ,其主要用来做可见性判断的
- m_ids:当前系统中那些活跃(未提交)的读写事务ID, 它数据结构为一个List。
- min_limit_id:表示在生成Read View时,当前系统中活跃的读写事务中最小的事务id,即m_ids中的最小值。
- max_limit_id:表示生成Read View时,系统中应该分配给下一个事务的id值。
- creator_trx_id: 创建当前Read View的事务ID
//可见性判断,trx_id为版本链中某个版本的事务id
if(trx_id < min_limit_id) return true;
if(trx_id >= max_limit_id) return false;
if(min_limit_id =<trx_id< max_limit_id){
if(!m_ids.contains(trx_id)) return true;
else if(m_ids.contains(trx_id) && trx_id==creator_trx_id) return true;
return false;
}
3. mvcc原理
3.1查询sql的流程
- 获取当前事务版本号(事务id),开启readview(readview 中记录m_ids,max_id,min_id以及creator_id)
- 查询数据以及数据的版本号(trx_id)
- 验证是否符合可见性原则,如果符合返回数据,如果不符合根据版本链找到上个版本继续验证
3.2 RC模式下与RR模式下处理可重复读
如上图所示,初始值为孙权,版本号100, 后事务B更新为曹操,版本号为101
在RC级别下
第一个select时,开启readview,参数如下:
| 变量 | 值 |
|---|---|
| m_ids | 100,101 |
| max_limit_id | 102 |
| min_limit_id | 100 |
| creator_trx_id | 100 |
最新数据版本为100, 根据可见性公式判断,数据可见,即第一次查询数据为孙权
第二个select时,开启readview,参数如下
| 变量 | 值 |
|---|---|
| m_ids | 100 |
| max_limit_id | 102 |
| min_limit_id | 100 |
| creator_trx_id | 100 |
最新数据版本为101,根据可见性公式判断,数据也可见,即第二次查询数据为曹操 此时, 不可重复读问题产生了
在RR级别下
第一个select时,开启readview,参数如下:
| 变量 | 值 |
|---|---|
| m_ids | 100,101 |
| max_limit_id | 102 |
| min_limit_id | 100 |
| creator_trx_id | 100 |
最新数据版本为100, 根据可见性公式判断,数据可见,即第一次查询数据为孙权
第二个select时,由于是RR级别,沿用之前的readview,参数如下
| 变量 | 值 |
|---|---|
| m_ids | 100,101 |
| max_limit_id | 102 |
| min_limit_id | 100 |
| creator_trx_id | 100 |
最新数据版本为101,根据可见性公式判断,数据不可见,即第二次查询数据为孙权