211_mysql_innodb_5_Innodb_mvcc

举报
alexsully 发表于 2021/11/09 23:43:32 2021/11/09
【摘要】 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

版本链对比
1 trx_id < min_id : 该版本已经提交 可见
2 trx_id > max_id : 该版本由未启动事物生成 不可见
3 min_id < trx_id < max_id 

a) trx_id 在数组中,说明未提交: 不可见
b) trx_id 不在数组中,说明已经提交: 可见

注:删除的情况 -> 特殊的update,会将版本链最新数据复制一份,将trx_id 修改成删除操作的trx_id,同时将该条记录的头信息(record header)里面的(delete flag)
标志位 写为true,表示当前记录已经删除,查询时,如果delete flag为true,不返回数据

事物并发执行遇到一致性的问题

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

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。