事务的基本要素(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的隔离级别设置为“读提交”。