MySQL的事务隔离级别
# MySQL的事务隔离级别
MySQL将事务分为不同的隔离级别,主要是为了解决在多事务并发场景下可能出现的数据一致性问题。通过不同级别的事务隔离,可以防止出现脏读
、不可重复读
和幻读
等问题。
# 事务的四大特性(ACID)
原子性(Atomicity):事务是不可分割的工作单位,事务中的操作要么全部成功,要么全部失败回滚。
一致性(Consistency):事务执行前后,数据库必须保持一致性状态。例如:A和B账户共有5000元,不管他们之间如何转账,事务结束后两账户的总金额应该仍然是5000元。
隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
持久性(Durability):一个事务一旦提交,其对数据库的修改就是永久性的,即使系统发生故障也不会丢失。
# 并发事务可能出现的问题
# 1. 脏读(Dirty Read)
当一个事务读取到另一个事务未提交的数据时,就会发生脏读。
示例:
- 事务A读取了事务B未提交的数据(余额100修改为200)
- 事务B随后回滚(余额恢复为100)
- 事务A使用了错误的数据(认为余额是200)
# 2. 不可重复读(Non-Repeatable Read)
在同一事务内,多次读取同一数据却得到不同的结果。
示例:
- 事务A第一次读取某行数据
- 事务B修改该行数据并提交
- 事务A再次读取该行数据,发现数据已变化
# 3. 幻读(Phantom Read)
在同一事务内,多次查询某个范围的记录,发现记录数量不一致。
示例:
- 事务A查询工资大于1000的员工数量为10人
- 事务B插入一条工资为1500的记录并提交
- 事务A再次查询,发现工资大于1000的员工变为11人
# 不可重复读vs幻读的区别
- 不可重复读:针对数据**更新(UPDATE)**操作
- 解决方案:行级锁
- 幻读:针对数据**插入(INSERT)和删除(DELETE)**操作
- 解决方案:表级锁或间隙锁
# MySQL的四种隔离级别
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
READ UNCOMMITTED(读未提交) | 可能 | 可能 | 可能 |
READ COMMITTED(读已提交) | 不可能 | 可能 | 可能 |
REPEATABLE READ(可重复读) | 不可能 | 不可能 | 可能 |
SERIALIZABLE(串行化) | 不可能 | 不可能 | 不可能 |
MySQL默认的隔离级别是REPEATABLE READ(可重复读)。
# 隔离级别的实现原理
MySQL通过多版本并发控制(MVCC)和锁机制来实现事务隔离:
MVCC(Multi-Version Concurrency Control):
- 每次更新操作都会生成一条回滚日志(undo log)
- 不同时间点启动的事务会创建不同的read-view
- 通过回滚日志可以找到数据的历史版本
回滚日志(undo log)管理:
- 当没有事务需要用到某个回滚日志时,该日志会被删除
- 系统中不存在比该回滚日志更早的read-view时,日志即可删除
# 如何查看和设置隔离级别
# 查看当前隔离级别
方式1:
SHOW VARIABLES LIKE 'transaction_isolation';
1
方式2:
SELECT @@transaction_isolation;
1
# 设置隔离级别
- 通过SET命令:
SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL level;
-- level可选值:
-- REPEATABLE READ
-- READ COMMITTED
-- READ UNCOMMITTED
-- SERIALIZABLE
1
2
3
4
5
6
7
2
3
4
5
6
7
- 通过启动参数:
--transaction-isolation=REPEATABLE-READ
1
不同作用域说明:
- GLOBAL:影响后续新的会话
- SESSION:影响当前会话的后续事务
- 无关键词:只影响下一个事务
上次更新: 4/24/2025