事务的基本要素(ACID)
- 原子性(Atomicity);事务开始后所有操作,要么全部做完,要么全部不做,不能停滞在中间环节。
- 一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏。
- 隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。
- 持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。
事务的并发问题
- 脏读:事务B修改数据但未提交,事务A读数据,然后B回滚,则A读到的是脏数据。
- 不可重复读:事务A第一次读取数据,事务B修改数据提交,事务A第二次读数据,两次数据不一致。
- 幻读:事务A update表的全部行,事务B插入一行,事务A就会发现表中还有未修改的行。(一般加间隙锁)
MySQL事务隔离级别
事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | 会 | 会 | 会 |
读已提交 | 不会 | 会 | 会 |
可重复读 | 不会 | 不会 | 会 |
串行话 | 不会 | 不会 | 不会 |
案例
事务A | 事务B |
---|---|
启动事务;查询得到值 | 启动事务 |
查询得到值1 | |
将1改成2 | |
查询得到值V1 | |
提交事务B | |
查询得到值V2 | |
提交事务A | |
查询得到值V3 |
若隔离级别是“读未提交”, 则 V1 的值就是 2。这时候事务 B 虽然还没有提交,但是结果已经被 A 看到了。因此,V2、V3 也都是 2。
若隔离级别是“读提交”,则V1是1,V2的值是2。事务B的更新在提交后才能被A看到。所以,V3的值也是2。
若隔离级别是“可重复读”,则 V1、V2 是 1,V3 是 2。之所以 V2 还是 1,遵循的就是这个要求:事务在执行期间看到的数据前后必须是一致的。
若隔离级别是“串行化”,则在事务 B 执行“将 1 改成 2”的时候,会被锁住。直到事务 A 提交后,事务 B 才可以继续执行。所以从 A 的角度看, V1、V2 值是 1,V3 的值是 2。
在实现上,数据库里面会创建一个视图,访问的时候以视图的逻辑结果为准。
- 在“可重复读”隔离级别下,这个视图是在事务启动时创建的,整个事务存在期间都用这个视图。
- 在“读提交”隔离级别下,这个视图是在每个SQL语句开始执行的时候创建的。
- 在“读未提交”隔离级别下直接返回记录下的最新之,没有视图概念。
- 而“串性化”隔离级别下直接用加锁的方式来避免并行访问。
为保证数据库隔离级别一致,你一定要记得将MYSQL的隔离级别设置为“读提交”。