MySQL6
MySQL中的事务隔离级别
在 MySQL 中,事务隔离级别主要有四种,它们定义了一个事务中的操作对其他事务可见性的强弱。从低到高分别是:
1. READ UNCOMMITTED(读未提交)
- 含义:一个事务可以读取到其他事务尚未提交的数据。
- 问题:会产生 脏读 (Dirty Read),即读到无效数据,如果该事务回滚,之前读取到的数据就不成立。
- 特点:性能最高,安全性最低。
2. READ COMMITTED(读已提交)
- 含义:只能读取到其他事务已经提交的数据。
- 解决:避免了脏读。
- 问题:仍可能发生 不可重复读 (Non-Repeatable Read),即同一条数据在同一个事务中两次读取结果不同,因为其他事务可能在中途修改并提交了。
- 特点:大部分数据库(如 Oracle)默认级别。
3. REPEATABLE READ(可重复读)
- 含义:在同一事务中,多次读取同一行数据时结果保持一致,即使其他事务更新了并提交。
- 解决:避免了 脏读 和 不可重复读。
- 问题:在标准 SQL 中仍可能出现 幻读 (Phantom Read) ——同一个查询在不同时间得到的结果集行数不同(例如新增了数据)。
- 特点:MySQL InnoDB 默认隔离级别。InnoDB 通过 间隙锁 (Gap Lock) 来避免幻读问题,所以实际上几乎不会出现幻读。
4. SERIALIZABLE(可串行化)
- 含义:事务串行执行,相当于对每个读操作都加锁,强制事务按顺序执行。
- 解决:避免了脏读、不可重复读、幻读,保证最高一致性。
- 问题:性能最差,可能大量锁等待和超时。
MySQL默认的事务隔离级别
在 MySQL(InnoDB 存储引擎) 中,默认的事务隔离级别是:
Repeatable Read
(可重复读)
为什么选择 Repeatable Read
?
-
兼顾一致性与性能
- 相比
Read Commited
,能避免不可重复读。 - 相比
Serializable
,它不会强制串行执行,性能更高。 - 在绝大多数 Oltp(在线事务处理)场景中是一种“高一致性 + 高性能”的折中选择。
- 相比
-
避免幻读(MySQL 特性)
- 在标准 SQL 定义下,
Read Commited
可能出现幻读。 - 但 InnoDB 通过 Next-Key Lock(记录锁 + 间隙锁) 机制,解决了幻读问题。
- 所以在 MySQL 中,
Read Commited
实际上能避免脏读、不可重复读和幻读。
- 在标准 SQL 定义下,
-
默认隔离级别:
REPEATABLE READ
-
好处:
- 避免脏读、不可重复读、幻读(InnoDB 特性)
- 性能与一致性平衡良好
-
选择原因:
- 提供比
Read Commited
更强的一致性 - 避免
Serializable
带来的性能损失
- 提供比
数据库的脏读、不可重复读和幻读
1. 脏读(Dirty Read)
定义:一个事务读取了另一个事务尚未提交的数据。
- 如果那个事务后来回滚,之前读到的数据就是无效的,称为“脏”的。
示例:
- 事务A修改了某行数据,但还未提交。
- 事务B读取了这个未提交的数据。
- 事务A回滚了,B读到的数据就不存在了。
影响:数据不一致,读到了错误信息。
可能出现的隔离级别:Read Uncommited
2. 不可重复读(Non-Repeatable Read)
定义:在同一个事务中,两次读取同一条记录,结果却不同。
- 因为在两次读取之间,另一个事务修改并提交了该记录。
示例:
- 事务A第一次读取某个用户余额 = 100。
- 事务B更新该用户余额 = 200 并提交。
- 事务A再次读取该用户余额,结果变成了 200。
影响:同一事务内,数据前后不一致。
可能出现的隔离级别:Read Commited
3. 幻读(Phantom Read)
定义:在同一个事务中,执行相同的条件查询,两次结果集的行数不一致。
- 因为在两次查询之间,另一个事务插入或删除了符合条件的新数据。
示例:
- 事务A查询“工资 > 10000 的员工”,结果有 5 行。
- 事务B插入了一条工资 > 10000 的新员工并提交。
- 事务A再次查询,结果有 6 行。
影响:同一事务内,查询范围结果集前后不一致。
可能出现的隔离级别:Repeatable Read
(在标准SQL中可能出现,但 MySQL InnoDB 通过间隙锁避免了)。
对比总结
问题 | 定义 | 典型场景 | 出现隔离级别 |
---|---|---|---|
脏读 | 读到未提交的数据 | 事务A回滚,事务B读到无效数据 | READ UNCOMMITTED |
不可重复读 | 同一事务内两次读取同一数据结果不同 | A两次读同一行,B修改提交了 | READ COMMITTED |
幻读 | 同一事务内两次范围查询,结果集行数不同 | A两次查询,B插入/删除了数据 | REPEATABLE READ(标准) |