Skip to content

事务隔离级别是怎么实现的?

献上一张图

image

事务的特性

事务的四个特性,ACID。原子性:atomicity,一致性:consistent,隔离性:isolate,持久性durability。

原子性:事务的操作必须是全部都完成,或者全部都失败,不会出现成功一部分,另一部分失败的情况。

一致性:事务前后,数据满足完整性约束,数据库保持一致的状态。

隔离性:数据库可以多个事务并发执行,不会互相干扰。

持久性给:事务完成后,对数据的修改是持久的,系统故障也不会消失。

InnoDB通过什么技术保证事务的四个特性?

持久性是通过redo log,重做日志保证的。 原子性是通过undo log,回滚日志保证的。 隔离性是通过MVCC(多版本并发控制)或者锁机制保证的。 一致性是前面三个特性保证。

并行事务存在什么问题?

同时处理多个事务的时候,可能会出现脏读、幻读、不可重复读的问题。

脏读

一个事务读取到了其他未提交事务修改过的数据,就称为产生了脏读。

不可重复读

一个事务前后读取一个数据,但是不一致,说明发生了不可重复读。

幻读

一个事务内多次查询某个数据的数量,如果前后两次数量不一样,说明发生了幻读。

SQL标准有四种隔离级别来规避这个现象。

如下:读未提交、读提交、可重复读、串行化。隔离级别越高,性能效率越低。

不同的隔离级别下,可能会发生的异常也不同。

i

MySQL的可重复读隔离级别可以很大程度避免幻读。

针对快照读,就是普通的select语句,MySQL通过MVCC方式解决幻读。可重复读隔离级别下,事务执行过程中看到的数据跟事务开始时的数据是保持一致的,不会受到其他事务的影响。

针对当前读,(如select ... for update等语句),是通过 next-key lock (记录锁+间歇锁)方式解决的幻读,因为执行当前读语句的时候,会加上临键锁,这样其他事务在锁范围内尝试插入记录的时候,这条插入语句就会被阻塞。

四种隔离级别是如何实现的呢?

读未提交和串行化都好理解,前者是直接读取最新数据即可,后者就阻塞呗。

重点是读已提交和可重复读。

它们是通过 Read View 实现的,但是区别在于Read View 的创建时机不同,它相当于一个数据快照。

读已提交是在每个语句执行之前重新生成Read View,也就是读视图,而可重复读是启动事务时创建Read View,整个事务期间使用这个读视图。

执行开始事务命令,不意味着启动事务

MySQL有两种开启事务的命令,分别是begin/start transaction 命令、 start transaction with consistent snapshot. 前者执行完毕后,开始执行第一条sql语句时才开始事务,后者立即开始事务。

Read View 在MVCC里是如何工作的?

image

MySQL可重复读级别,完全解决了幻读问题吗?

wow!