211_mysql_innodb_5_Innodb_mvcc
MVCC 多版本并发控制,利用版本链 ReadVIEW开控制事务访问记录的行为
Readview 一致性视图
m_ids: 生成一致性视图时候,当前系统活跃的读写事物id列表
min_trx_id: 当前活跃读写事物中最小的事物id, m_ids中的最小值
max_trx_id: 系统分配给下一个事物id (可以简单理解为活跃事务中最大的事务ID)
creator_trx_id: 生成该readview的事物id
btw: max_trx_id 非m_ids最大值,1,2,3 三个事物,3已经提交,生成m_ids时 仅有1,2 max_trx_id 应该是4
判断可见性
1 如果被访问记录版本的 trx_id == create_trx_id, 说明事物在访问自己修改的记录,该版本记录可以被访问
2 如果被访问记录版本的trx_id < ReadView的 min_trx_id, 说明被访问记录早已提交,可以被访问
3 如果被访问记录版本的 trx_id >= ReadView的 max_trx_id 说明该记录是 该记录版本的事物晚于 readview开启时间,不能被访问到
4 如果被访问记录版本的 min_trx_id < trx_id < max_trx_id 需要进一步判断
4.1 如果 trx_id 在 m_ids 列表中,说明创建readview时候,trx_id对应的事物是活跃的,该版本不能被访问
4.2 如果 trx_id 不在m_ids 列表中,说明 trx_id 事务已经提交, 该版本可以访问
使用read commited 隔离级别的事物,每次查询都会生成 readview
使用 repeatable read 隔离级别的事物,第一次查询时候生成 readview 之后不会再生成
使用start transaction with consistent snapshot 在RR模式下,会立即生成一个readview,不会等到第一个select
二级索引&MVCC
1 二级索引面的 page header部分有个属性: PAGE_MAX_TRX_ID, 一个事物如果只选增删改时候 修改了此页面 且事物ID > PAGE_MAX_ID,则将事物id赋值给 PAGE_MAX_TRX_ID
2 如果一条 select 访问,
如果 readview 中的min_trx_id > PAGE_MAX_TRX_ID, 则该页面中所有记录都可见,
如果 min_trx_id < PAGE_MAX_TRX_ID 就利用聚簇索引会表,找到对该readview可见的第一个版本,进行查询
transaction 100 | transaction 200 | transaction 300 | #select1 | #select2 |
begin | begin | begin | begin | begin |
update test set xxx | ||||
update test set xxxx | ||||
update acc set name="a" where id=1 | ||||
commit | ||||
select name from acc where id=1 [100,200] 300 | ||||
update acc set name="b" where id=1 | ||||
update acc set name="c" where id=1 | ||||
select name from acc where id=1 | ||||
commit | update acc set name="bb" where id=1 | |||
update acc set name="cc" where id=1 | ||||
select name from acc where id=1 | select name from acc where id=1 [200], 300 | |||
commit |
执行查询SQL 生成readview : 未提交事物ID数组(数组里最小id为 min_id) 和已经创建的最大事物id (max_id)组成例 [100,200] 300 版本链对比 a) trx_id 在数组中,说明未提交: 不可见 注:删除的情况 -> 特殊的update,会将版本链最新数据复制一份,将trx_id 修改成删除操作的trx_id,同时将该条记录的头信息(record header)里面的(delete flag) |
事物并发执行遇到一致性的问题
1 脏写
一个事物修改了另一个未提交事物修改的数据
2 脏读
一个事物读取了另一个未提交事物修改的数据
3 幻读/不可重复读
如果一个事物A先按某个条件查询出一些结果集,另一个事物写入了一些符合条件的记录(insert/delete/update),事物A再查询时候,结果集不一致
本质: A事物读取一条记录, B事物对该记录进行了修改
备注:某论文定义 insert行为- 幻读, 更新((insert/delete/update))- 不可重复读
解决不一致的方式(隔离级别)
隔离级别 |
脏读 |
不可重复读 |
幻读 |
READ UNCOMMITED |
可能 |
可能 |
可能 |
READ COMMITED |
不可能 |
可能 |
可能 |
REPEATABLE READ |
不可能 |
不肯能 |
可能 |
SERIZLIZABLE |
不可能 |
不可能 |
不可能 |
MySQL隔离级别:5.7.20之前: tx_isolation, 之后是 transaction_isolation
- 点赞
- 收藏
- 关注作者
评论(0)