上一篇,我们介绍了 SQL92标准中事务的四种隔离级别,并讨论了每种隔离级别下 脏读、不可重复读、幻读 问题是否可以解决:
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交:Read Uncommitted | ✔ | ✔ | × |
读已提交:Read Committed | × | ✔ | × |
可重复读:Repeatable Read | × | × | ✔ |
串行化:Serializable | × | × | × |
在 读已提交(Read Committed) 和 可重复读(Repeatable Read)两种隔离级别上,数据库底层采用了快照读(Snapshot Read)的模式来实现高并发机制。
那RC 和 RR这两种的隔离级别上的快照读(Snapshot Read)有什么区别呢,咱们往下探索?
MySQL中InnoDB存储引擎的快照读(Snapshot Read)是一种读取数据的方式,它可以在事务开始时创建一个数据快照,这个快照是一致性的,即读取在事务开始时或特定时间点之前提交的数据。底层原理是MySQL使用多版本并发控制(MVCC)机制来实现快照读。在MVCC中,每个事务读取的数据都是根据事务开始时间点或快照时间点确定的。MySQL通过为每一行数据添加版本信息(如创建版本、删除版本等),来保留历史数据的多个版本。通过一种不加锁一致性读(Consistent Nonlocking Read)的方式来实现高并发的能力。
事务执行顺序如下:
时间序列 | A事务 | B事务 |
---|---|---|
T1 | 开始事务 | |
T2 | 开始事务 | |
T3 | 查询xx账户余额(假设默认有500元) ★SELECT balance FROM acount WHERE customer_id=123456; |
|
T4 | xx账户存入1000元(未提交) ★UPDATE acount SET balance=balance+1000.00 WHERE customer_id=123456; |
|
T5 | 查询A账户余额 | |
T6 | 提交事务 ★commit; |
|
T7 | 查询A账户余额 |
事务执行顺序如下:
时间序列 | A事务 | B事务 |
---|---|---|
T1 | 开始事务(假设默认有500元) | |
T2 | 开始事务 | |
T3 | xx账户存入1000元(未提交) ★UPDATE acount SET balance=balance+1000.00 WHERE customer_id=123456; |
|
T4 | 提交事务 ★commit; |
|
T5 | 查询A账户余额 ★SELECT balance FROM acount WHERE customer_id=123456; |
首先,事务总能够读取到自己写入(update /insert /delete)的行记录。而其他事务的提交,则分情况。
RC模式,快照读总是能读到最新的行数据快照,当然,必须是已提交事务写入的。
RR模式,某个事务首次read记录的时间为T1,之后的操作不会读取到T1时间之后已提交事务写入的记录,以保证连续相同的read读到相同的结果集。
简单点说: