为什么有事务和隔离级别

事务是对一组操作原子性的保障,但正是由于事务,就会出现事务A和事务B数据之间的可见性问题(脏读,幻读,不可重复读)为了解决问题,才设置了隔离级别这种东西 。

隔离级别的一种实现思想就是mvcc,一行数据由于多个事务的修改可能会有多个版本。

隔离级别的实现

读未提交

每次读取的是数据最新版本。

串行化

事务之间不是并发执行的。

读取已提交

事务在每次执行语句时会创建新的快照,关闭之前的快照。

可重复读

事务开始执行,准确的说是事务第一次select时会创建快照,后续的读操作都是从快照里去读数据。

快照

是什么

是对数据库的临时拷贝,有个经常听到的说法是,可重复读是在事务开始时候的产生一个快照,但这个快照是什么意思,如果事务开始时,数据库是100G,那么我产生的快照也要100G吗,但显然不是的。
一行数据多个版本,如果每个事务知道自己要访问的版本,想象一个对象,每次事务创建一个对象,然后事务需要判断行数据的可见性时,调用这个对象就能知道结果,那我们就可以认为它是一个快照。

如何实现

我们知道,一行数据在数据库中会有多个版本,每个版本其实都记录了一个事务id(row trx_id),row trx_id和read-view就能实现一个快照的功能。

read-view

是什么

是 InnoDB 在实现 MVCC 时用到的一致性读视图,即 consistent read view,用于支持 RC(Read Committed,读提交)和 RR(Repeatable Read,可重复读)隔离级别的实现。

如何实现

为每个事务构造了一个数组,用来保存这个事务启动瞬间,当前正在“活跃”的所有事务 ID。

“活跃”指的就是,启动了但还没提交。数组里面事务 ID 的最小值记为低水位,当前系统里面已经创建过的事务 ID 的最大值加 1 记为高水位。

这个视图数组和高水位,就组成了当前事务的一致性视图(read-view)

InnoDB快照如何判断一行数据的可见和不可见的

mysql事务隔离性的理解

这样,对于当前事务的启动瞬间来说,一个数据版本的 row trx_id,有以下几种可能:

如果落在绿色部分,表示这个版本是已提交的事务或者是当前事务自己生成的,这个数据是可见的;

如果落在红色部分,表示这个版本是由将来启动的事务生成的,是肯定不可见的;

如果落在黄色部分,那就包括两种情况

a. 若 row trx_id 在数组中,表示这个版本是由还没提交的事务生成的,不可见;

b. 若 row trx_id 不在数组中,表示这个版本是已经提交了的事务生成的,可见。

参考文献:

事务到底是隔离的还是不隔离的?

相关文章: