事务特性
MySQL数据库InnoDB存储引擎的事务完全符合事务ACID的特性。
- A:原子性(Atomicity)
例如:A向B转账,A账户扣除100块,B账户增加100块,这2个操作要么都成功,要么都失败,如果有一个操作执行成功,一个执行失败,执行成功的操作需要回滚。 - C:一致性(Consistency)
一致性指事务将数据从一种状态转变为下一种一致的状态。在事务开始之前和事务结束之后,数据库的完整性约束没有被破坏。
应用系统从一个正确的状态到另一个正确的状态,ACID就是说事务能够通过AID来保证这个C的过程,C是目的,AID是手段 - I :隔离性(Isolation)
两个操作数据库的事务互相之间不受彼此影响。 - D:持久性(Durability)
事务一旦提交,数据是持久化的,不会丢失,即使数据库宕机也能恢复数据。
事务并发问题
当 多个事务同时访问同一缓存页中的的同一批数据时,会出现一系列问题
- 脏读:事务A读取到了事务B未提交的数据,事务B回滚,事务A读取到的数据就是脏数据
- 不可重复读:事务A多次读取同一数据,期间事务B对数据进行了修改,事务A再次读取时,发现读取到的数据与一开始不一致
- 幻读:事务A查询id>1的数据,只查到了1条,期间事务B向表中插入了一条id=2的数据,事务A再次以相同条件查询时,发现有2条数据,多了一行,多的一行官网称为“幻行”,这种现象称为幻读
事务隔离级别
SQL标准中定义了如下事务隔离级别
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交(read uncommitted) | √ | √ | √ |
读已提交 ( read committed ) | x | √ | √ |
可重复读 ( repeatable read) | x | x | √ |
串行化 ( serialiable) | x | x | x |
在 MySQL 中同样实现了上述的4个隔离级别,但是在 可重复读级别不会发生幻读的情况。
测试用例
启用两个客户端A,B
- Read Uncommitted(读未提交)
设置两个客户端的事务隔离级别为 read uncommited
看如下1-5顺序执行,事务A读取到了事务B未提交的数据。导致脏读
- Read Committed(读已提交)
设置两个客户端的事务隔离级别为 read uncommited
下图按1-7步骤执行,事务A读取到了事务B已提交的数据。导致两次读取id=1的数据不一致,造成不可重复读
- Repeatable Read(可重复读)
可重复读级别下,事务A读取不到事务B更新的数据,多次读取同一数据结果一致,不会造成不可重复读。
在可重复读隔离级别下,事务B往表中插入一条数据,插入数据前后,事务A查询 id>3 的数据始终只有2条,没有出现数据多的情况(即幻读)
- Serializable(串行化)
串行的执行事务,不会有脏读,不可重复读,幻读等问题发生,但是性能极差。