1. 前言

MySQL 中事务(Transaction)的定义是对于一个或者多个 SQL 语句,要么全部执行成功,要么一个都不执行成功。在实际应用场景中,有很多需要事务的场景,例如在电商网站,顾客下单、付款以及商品扣减库存就应该在一个事务中执行,如果不能保证事务特性,就可能出现用户已经下单并且成功付款,但是在扣减库存逻辑出现异常,发货失败的情况。所以事务中的某个环节出现异常,之前执行的所有 SQL 语句都应该回滚。

2. 事务

2.1 事务 ACID 特性

面试官提问: MySQL 中事务的特性是什么?

题目解析:

ACID 是衡量事务的 4 个维度,分别的定义是:

(1)原子性(Atomic,简写 A):原子性要求事务是一个不可分割的执行单位,如果一个事务包含多条 SQL 语句,要么所有的 SQL 都执行成功,要么所有的 SQL 都执行失败,不存在两者之间的中间状态。如果事务中的任意一条 SQL 执行失败,那么已执行成功的也需要回滚。MySQL 中 InnoDB 引擎利用 undo log 实现原子性,undo log 记录了所有已执行的 SQL 记录,如果事务执行失败调用了 rollback 语句,那么使用 undo log 的记录回滚已执行的 SQL。
(2)持久性(Durability,简写 D):持久性要求事务一旦提交(commit),对数据库的改变就应该是永久的,其他的操作不会对已提交的事务有影响。InnoDB 引擎中使用 redo log 实现持久性,如果 MySQl 服务器宕机,那么在重启时可以读取 redo log 中的记录恢复数据库。
(3)隔离性(Isolation,简写 I):要求一个事务的执行不受到其他并发执行事务的影响。
(4)一致性(Consistency,简写 C):事务将数据库从一种状态转换到另一种状态,但是两种状态从数据上是一致的。例如用户下单扣库存让库存减少了一个单位,那么在订单中就会增加一个单位的商品,库存和订单中的商品数量和是不会改变的。

2.2 事务隔离级别

面试官提问:ACID 特性中的隔离性在 MySQL 中的具体定义是什么?

题目解析:

MySQL 提供了 4 种事务隔离级别,分别是:

(1)读未提交(Read Uncommitted):所有事务可以看到其他事务未提交的执行结果;
(2)读已提交(Read Committed):所有事务只能看到其他事务已提交的执行结果;
(3)可重复读(Repeatable Read):MySQL 默认的隔离级别,所有事务能看到其他事务已提交后的修改后数据,但是如果第一次读取到这个修改后的数据,如果其他事务继续修改了数据并且提交,这个事务读到的也是第一次读到的值,不会读到修改后的新值。
(4)串行化(Serializable):最高隔离级别,可以理解为让所有并发执行的事务都进入队列,挨个串行执行,永远不可能发生冲突。

我们关注事务,关注点在于不同事务的并发冲突,而且重点在于读写操作。对于同一条数据,在执行并发事务时可能会产生读写上的问题,有三种:

(1)脏读(Dirty Read):如果事务 A 更新了一份数据,比如将记录 a 更新为记录 b,那么在事务 B 中读取到的记录是 b,此时事务 A 进行了回滚操作,记录 b 回滚为记录 a,那么事务 B 读到的记录 b 则是非法数据。
(2)不可重复读(Non-Repeatable Read):如果事务 A 更新了一份数据,比如将记录 a 更新为记录 b,那么在事务 B 中读取到的记录是 b,此时事务 A 继续将记录 b 更新为记录 c,那么事务 B 第二次读到的记录是 c,两次读取的结果不同。
(3)幻读(Phantom Read):如果事务 B 查询到了几行数据,此时事务 A 又插入了几行新数据,那么事务 B 会读到多出来的几行数据,读到了上次读取没出现的数据。

4 种隔离级别对应的问题应对能力如下表:

隔离级别 脏读 不可重复读 幻读
读未提交
读已提交
可重复读
串行化

从解决问题的能力上看,串行化能解决所有的并发读写问题,但是串行执行效率太低,比如在电商网站的秒杀商品下单流程,就会导致所有的用户需要等某一个用户执行完下单操作后才能继续抢购,不具有实战意义。MySQL 默认的隔离级别是可重复读,这个级别能解决脏读和不可重复读的问题,效率上相对比较快。读未提交的执行效率最高,但是数据的一致性保障最差, 一般不会在实战中使用。

在 MySQL 客户端执行 show variables like 'transaction_isolation'; 语句可查看隔离级别:

图片描述

MySQL 默认隔离级别

3. 小结

本小结概括了事务的 ACID 特性以及 4 种隔离级别的定义,候选人可以自行使用小样本数据测试 MySQL 不同隔离级别下事务的读写区别。