事务原理
事务具有四大特性, 原子性, 隔离性, 一致性, 持久性
- 原子性: 指的是一个事务操作是不可分割的, 执行要么全部成功, 要么全部失败
- 隔离性: 指的是, 多个事务并发操作时, 互相是隔离的, 某事务不该被其他事务所干扰
- 一致性: 指的是事务遵循数据的完整性,唯一性约束
- 持久性: 指的是事务如果已经提交, 那么对数据的变更就是永久的
在谈原理之前, 我想先假设出一个事务场景, 并提出一些问题, 以便更好的理解事务原理:
- 都知道Mysql的隔离级别有四种: 读未提交, 读已提交, 可重复读, 序列化读
- 四种隔离级别是如何实现的?
- 原子性是不可分割的
- 那么, 全不成功, 进行回滚, 如何实现恢复为原始数据的回滚过程呢?
- 全部成功, 进行提交, 如何实现数据在磁盘上的真实更新的呢?
- 持久性说, 事务已提交对数据的变更就是永久的. Mysql如何保障的, 提交总是要更新磁盘(后文用刷盘指代)的吧?
- 假设是先刷盘后提交, 那么在刷盘的时候宕机了, 该怎么恢复处理呢?
- 假设是先提交后刷盘, 那么在刷盘的时候宕机了, 该怎么恢复处理呢?
我们通常默认使用 InnoDB
作为存储引擎, 那么, 接下来, 从问题出发, 讨论 InnoDB事务原理
吧
四种隔离级别是如何实现的?
在此之前, 先重新整理下, 已知的四种隔离级别
假设有事务A, B同时并发操作同一条数据, 事务A查询数据, 事务B更新数据.
- 读未提交: 事务A会查询到事务B未提交却修改过的数据, 若是事务B回滚, 事务A读取的数据将是不正确的, 即: 脏读
- 读已提交: 事务A仅可查询事务B提交成功后的数据, 但若是事务A进行先后两次查询(重复读), 将出现前后数据不一致的情况, 即: 不可重复读
- 可重复读: 保证了在事务A重复读, 不受其他事务更新的影响, 前后数据一致, 但若有其他事务插入数据, 重复读将出现, 后读数据集更多的情况, 即: 幻读
- 序列化读: 所有事务排队, 一条条的处理, 完美解决并发出现的问题
自上而下, 隔离级别越高, 事务之间的影响也越来越小, 越来越隔离, 数据越来越安全
同样的, 性能也越来越低, 当开启序列化读, 巨量事务排队的情况, 数据的安全性是拉满了, 可性能却不尽人意
Mysql的默认事务隔离级别是: 可重复读
那么, 接下来介绍, 如何实现这四种隔离级别的呢?
标准SQL事务隔离级别实现原理
解决并发事务的常见方式, 就是通过悲观锁来进行并发控制了, 标准SQL事务隔离级别的实现是依赖锁的, 我们看看它是如何实现的:
1.
多版本并发控制(MVCC)
1 | 通俗的讲,数据库中同时存在多个版本的数据,并不是整个数据库的多个版本,而是某一条记录的多个版本同时存在. |