隔离性(Isolation)是数据库事务的ACID四大特性之一,指多个并发执行的事务彼此之间相互隔离,一个事务的执行不应受到其他并发事务的干扰,从而保证数据的一致性和正确性。隔离性通过事务隔离级别(如读未提交、读已提交、可重复读、串行化)来实现,不同级别在性能与一致性之间进行权衡:级别越高,隔离越强,但并发性能可能越低;级别越低,允许更多并发,但可能出现脏读、不可重复读或幻读等问题。
常见的隔离级别及对应问题:
- 读未提交(Read Uncommitted):可能产生脏读、不可重复读、幻读;
- 读已提交(Read Committed):避免脏读,但仍可能有不可重复读和幻读;
- 可重复读(Repeatable Read):避免脏读和不可重复读(MySQL InnoDB默认),但可能有幻读(InnoDB通过间隙锁/Next-Key Lock解决部分幻读);
- 串行化(Serializable):最高隔离级别,完全避免所有并发问题,但以牺牲并发性能为代价。
实现机制通常依赖于锁(如行锁、表锁、间隙锁)或无锁技术(如MVCC,多版本并发控制),例如 PostgreSQL 和 MySQL InnoDB 均采用 MVCC 提升读操作的并发性,同时结合锁机制处理写冲突。
脏读(Dirty Read):事务A修改了某行数据但尚未提交,事务B在此期间读取了该未提交的修改;若事务A随后回滚,事务B读到的就是“脏”数据(即从未真实存在的数据)。
✅ 规避:设置隔离级别 ≥ 读已提交(Read Committed),该级别下事务只能读取已提交的数据。
不可重复读(Non-Repeatable Read):事务A在同一次事务中两次读取同一行数据,但两次结果不一致——因为事务B在A两次读取之间修改并提交了该行。例如:第一次查余额为100元,B转账+50元并提交,A第二次查变为150元。
✅ 规避:设置隔离级别 ≥ 可重复读(Repeatable Read),该级别通过快照读(MVCC)或行锁保证同一事务内多次读取结果一致。
幻读(Phantom Read):事务A按条件查询一批记录(如 SELECT * FROM t WHERE age > 20),事务B在此期间插入一条满足该条件的新记录并提交,A再次执行相同查询时发现“多出一行”,像幻觉一样。注意:幻读本质是新行的插入(或删除)导致结果集行数变化,而非单行值变更(后者属不可重复读)。
✅ 规避:
- 严格意义上,仅 串行化(Serializable) 可完全避免幻读(通过范围锁或全表锁);
- 但在 MySQL InnoDB 中,可重复读(RR)级别已通过 Next-Key Lock(行锁 + 间隙锁)阻止幻读(针对当前读,如
SELECT ... FOR UPDATE或UPDATE/INSERT);而快照读(普通SELECT)则依赖 MVCC 快照,天然不感知新插入,故“逻辑上”无幻读——但标准 SQL 定义中,RR 级别仍被认为可能产生幻读(因新插入行可被当前读看到)。因此,是否“解决幻读”需区分读类型与数据库实现。
📌 总结规避路径:
| 问题类型 | 最低有效隔离级别 | 关键机制 |
|---|---|---|
| 脏读 | 读已提交 | 拒绝读未提交变更(MVCC可见性判断 / 行锁等待) |
| 不可重复读 | 可重复读 | MVCC快照固定 / 行级共享锁(读已提交用短锁,可重复读用长锁或快照) |
| 幻读 | 串行化(标准) MySQL RR(实践) | Next-Key Lock(锁定索引区间)或序列化调度 |
-- 示例:MySQL 中演示幻读防范(RR级别)
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
SELECT * FROM users WHERE age > 25; -- 返回3条
-- 此时另一事务插入 age=30 的用户并 COMMIT
SELECT * FROM users WHERE age > 25; -- 仍返回3条(快照读)✅
SELECT * FROM users WHERE age > 25 FOR UPDATE; -- 当前读,触发Next-Key Lock,阻塞插入或检测冲突 ✅
COMMIT;

850

被折叠的 条评论
为什么被折叠?



