mysql 事务隔离级别的实现原理

目录

 

一、事务的四要素(ACID)

二、mysql的事务的隔离级别

三、多版本并发控制(multi-version concurrency control)

3.1 功能

3.2 原理


一、事务的四要素(ACID)

1. 原子性(atomicity):all done  或者 all not  done

2. 一致性(consistency):事务开启和结束之后,数据的完整性没有被破坏

3. 隔离性(isolation):一个事务的执行不能被另一个事务干扰

4. 持久性 (durability):事务一旦提交,对于数据库的变更是永久性的

二、mysql的事务的隔离级别

隔离级别 脏读 不可重复读 幻读
读未提交(read uncommitted) ✔️ ✔️ ✔️
读已提交(read committed) ✔️ ✔️
可重复读(repeatable read) ✔️
串行化(serializable)

默认的隔离级别是:可重复读(repeatable read)

 

脏读:事务A读了事务B更新但未提交的数据,事务B回滚之后,A读到的就是脏数据

不可重复读:事务A需要多次读同一数据,事务B在事务A读数据的过程中,对数据进行了更新,则A多次读同一数据,结果不一致

幻读:事务A读某一个数据,其他事务又执行了插入操作,事务A再次按照同一条件查询时,数据变多了

 

三、多版本并发控制(multi-version concurrency control)

3.1 功能

       使得InnoDB在read committed和 repeatable read两种隔离级别下的一致性读有了保障。换句话说,在这两种隔离级别下,每个事物执行普通的select时,查询到的都是已经提交的数据或是当前事务更新的数据。这个技术是一项非常强大的技术,可以使得查询操作不用等待锁释放就能执行。当然这并不是一项通用技术,一些其他的数据库产品以及mysql的其他存储引擎并不支持。

3.2 原理

3.2.1 版本链

InnoDB存储引擎会给数据库的每一行增加三个隐藏字段

1. row_id:如果存在主键或是非NULL唯一键,该字段非必须

2. trx_id:事务ID,每次对某一个记录进行更新时,会把更新这条记录的事务ID赋值给隐藏的trx_id字段

3. roll_ptr:每次对某条记录进行修改时,这个隐藏列会存一个指针,可以通过这个指针找到修改之前的数据

3.2.2 ReadView

ReadView中包含4个主要内容:

(1) m_ids:生成当前ReadView时,当前系统中的活跃事务列表

(2)min_trx_id:生成当前ReadView时,当前当前系统中最小的活跃事务Id,即m_ids中的最小值

(3)max_trx_id:生成当前ReadView时,系统应该给下一个事务分配的id值

(4)creator_trx_id:生成当前ReadView的事务Id


注意:max_trx_id并不是m_ids中的最大值,事务ID是递增分配的。

e.g. 比如m_ids中有1,2,3三个活跃事务,之后事务3提交了,那么生成新的ReadView时,m_ids中只有1,2两个事务,而max_trx_id=4


3.2.3 一致性读(consistent read)

对于读已提交和可重复读两种隔离级别,可以借助ReadView,按照如下规则实现一致性读:

(1)如果被访问版本的trx_id与creator_trx_id相同,则表示当前事务正在访问自己修改的版本,该版本数据对当前事务可见;

(2)如果被访问版本的trx_id小于min_trx_id,则表示生成该ReadView时,当前版本的数据已经提交,该版本数据对当前事务可见;

(3)如果被访问版本的trx_id大于max_trx_id,表示生成该ReadView时,该版本的事务还未开启,该版本的数据对当前事务不可见;

(4)如果被访问版本的trx_id大于min_trx_id,小于max_trx_id,就需要判断当前版本的trx_id是否在m_ids中。如果在,则表示当前版本还为提交,该版本数据不可用;如果不在,则表示该版本数据已经提交,该版本数据可以被当前事务访问

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章