MySQL 的 ACID 特性与事务隔离级别(RU RC RR S)
·
在数据库系统中,事务(Transaction)是保证数据一致性的重要机制。MySQL 通过 ACID 特性 确保事务的可靠性,并通过 不同的事务隔离级别 控制并发事务对数据的影响。本篇文章将详细介绍 MySQL 的 ACID 特性,并解析 事务的四种隔离级别(RU、RC、RR、S),帮助开发者理解 如何在保证数据一致性的同时优化数据库性能。
1. MySQL 的 ACID 特性
ACID 是数据库事务必须满足的四个关键特性,分别是:
| ACID 特性 | 含义 | 作用 |
|---|---|---|
| A(原子性,Atomicity) | 事务中的操作要么全部成功,要么全部失败 | 确保事务完整执行,防止数据部分提交 |
| C(一致性,Consistency) | 事务执行前后,数据库保持一致状态 | 事务不会破坏数据库的完整性 |
| I(隔离性,Isolation) | 并发事务之间互不干扰 | 控制事务间的可见性,防止数据竞争 |
| D(持久性,Durability) | 事务提交后,数据永久保存 | 即使系统崩溃,数据也不会丢失 |
2. 事务隔离级别(RU/RC/RR/S)
MySQL 提供四种事务隔离级别,用于控制 并发事务之间的可见性,分别是:
| 隔离级别 | 可能发生的问题 | 性能 | 默认值(InnoDB) |
|---|---|---|---|
| RU(Read Uncommitted,读未提交) | 可能发生 脏读 | 最高 | ❌ |
| RC(Read Committed,读已提交) | 可能发生 不可重复读 | 高 | ❌ |
| RR(Repeatable Read,可重复读) | 可能发生 幻读 | 中 | ✅(默认) |
| S(Serializable,可串行化) | 不会发生任何问题,但并发性最差 | 低 | ❌ |
3. 事务隔离级别详解(RU/RC/RR/S)
3.1 读未提交(Read Uncommitted,RU)
特性
- 事务可以读取 其他事务未提交的数据。
- 可能发生脏读(Dirty Read),即一个事务读取到 另一个事务尚未提交的数据。
示例
事务 A 修改了 balance,但尚未提交:
-- 事务 A
START TRANSACTION;
UPDATE accounts SET balance = 5000 WHERE id = 1;
-- 事务 A 尚未提交
此时,事务 B 读取 balance:
-- 事务 B
SELECT balance FROM accounts WHERE id = 1;
-- 结果:balance = 5000
如果事务 A 回滚,事务 B 读取的数据将变得无效(脏数据)。
适用场景
- 适用于 对数据一致性要求不高的场景,如日志记录、临时数据存储。
- 一般不建议在生产环境使用,因为数据可能不可靠。
3.2 读已提交(Read Committed,RC)
特性
- 事务 只能读取其他事务已提交的数据,避免了 脏读。
- 可能发生不可重复读(Non-repeatable Read),即 同一个事务内多次查询相同数据,结果可能不同。
示例
事务 A 先查询 balance,事务 B 修改并提交了 balance,事务 A 再次查询数据,发现值已变更。
-- 事务 A:第一次查询
SELECT balance FROM accounts WHERE id = 1;
-- 结果:balance = 1000
-- 事务 B:修改并提交
START TRANSACTION;
UPDATE accounts SET balance = 5000 WHERE id = 1;
COMMIT;
-- 事务 A:再次查询
SELECT balance FROM accounts WHERE id = 1;
-- 结果:balance = 5000(发生不可重复读)
适用场景
- 适用于 大多数应用,如 银行转账、支付系统,避免读取未提交数据导致数据不一致。
- Oracle、SQL Server 默认使用
Read Committed作为事务隔离级别。
3.3 可重复读(Repeatable Read,RR)(MySQL 默认)
特性
- 事务内 多次读取相同的数据,保证读取结果一致,避免 脏读 和 不可重复读。
- 但 可能发生幻读(Phantom Read),即事务查询的数据范围发生变化,如 新增数据未被感知。
示例
事务 A 读取表 accounts,事务 B 插入新数据,事务 A 再次查询,发现结果多了一行。
-- 事务 A:第一次查询
SELECT * FROM accounts WHERE balance > 1000;
-- 结果:3 行数据
-- 事务 B:新增一条数据并提交
START TRANSACTION;
INSERT INTO accounts(id, balance) VALUES (4, 2000);
COMMIT;
-- 事务 A:再次查询
SELECT * FROM accounts WHERE balance > 1000;
-- 结果:4 行数据(发生幻读)
MySQL InnoDB 如何避免幻读?
- MySQL 通过 MVCC(多版本并发控制) 实现
Repeatable Read,在SELECT时读取快照版本,而不是最新数据。
适用场景
- 适用于金融交易、订单系统等场景,确保事务内部数据一致。
- MySQL 默认采用
Repeatable Read(RR),性能和一致性较为平衡。
3.4 串行化(Serializable,S)
特性
- 最高级别隔离,完全避免 脏读、不可重复读、幻读。
- 强制事务串行执行,每个事务必须等前一个事务完成后才能执行,导致 并发性能极低。
示例
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
START TRANSACTION;
SELECT * FROM accounts WHERE balance > 1000;
- 所有
SELECT语句都会加共享锁(S 锁),阻止其他事务的INSERT/UPDATE/DELETE。
适用场景
- 适用于 高一致性要求的金融系统,但性能开销大,通常不会用于高并发环境。
4. 结论
- ACID 保障事务的可靠性,MySQL 默认支持事务的 原子性、一致性、持久性。
- MySQL 提供 4 种事务隔离级别,默认是
Repeatable Read(RR),适用于大多数业务场景。 - 不同隔离级别适用于不同的应用需求,开发者需要根据业务需求权衡 数据一致性与性能。
📌 有什么问题和经验想分享?欢迎在评论区交流、点赞、收藏、关注! 🎯
更多推荐
所有评论(0)