数据库的隔离级别有哪些?它们分别解决了哪些并发问题(脏读、不可重复读、幻读)?MySQL/PostgreSQL的默认隔离级别是什么?
数据库的隔离级别是为了解决多个事务并发执行时可能出现的一致性问题(脏读、不可重复读、幻读)而设计的,SQL标准定义了4种隔离级别,从低到高依次为:读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read)、串行化(Serializable)。
一、隔离级别及解决的并发问题
首先明确三个核心并发问题的定义:
- 脏读:事务A读取到事务B未提交的修改(若B后续回滚,A读取的数据是“无效”的)。
- 不可重复读:事务A内两次读取同一行数据,结果不同(因事务B在两次读取之间修改并提交了该数据)。
- 幻读:事务A内两次查询同一范围的数据(如
WHERE id < 10
),结果行数不同(因事务B在两次查询之间新增/删除了符合条件的行)。
1. 读未提交(Read Uncommitted)
- 原理:事务对数据的修改即使未提交,其他事务也能看到(“脏数据可见”)。
- 解决的问题:无(是最低隔离级别,所有并发问题都可能发生)。
- 适用场景:极少使用,仅在对一致性要求极低、追求极致性能时(如临时统计无关紧要的日志)。
2. 读已提交(Read Committed, RC)
- 原理:事务只能读取其他事务已提交的修改(“提交后可见”)。
- 解决的问题:解决脏读(未提交的修改不可见)。
- 仍可能存在的问题:不可重复读、幻读。
- 适用场景:对一致性有基本要求,但允许偶尔的不可重复读(如普通业务系统的大部分查询场景,PostgreSQL默认级别)。
3. 可重复读(Repeatable Read, RR)
- 原理:事务启动后,对数据的读取结果始终与启动时一致(“快照读”),不受其他事务提交的修改影响。
- 解决的问题:解决脏读和不可重复读(同一事务内重复读数据结果不变)。
- 仍可能存在的问题:部分幻读(InnoDB通过“间隙锁”进一步解决了幻读,使RR级别接近串行化)。
- 适用场景:对一致性要求较高,需避免不可重复读(如订单、支付等核心业务,MySQL默认级别)。
4. 串行化(Serializable)
- 原理:强制所有事务串行执行(相当于单线程),事务之间完全隔离,不存在并发冲突。
- 解决的问题:解决所有并发问题(脏读、不可重复读、幻读)。
- 缺点:并发性能极差(事务排队执行)。
- 适用场景:对一致性要求极高,但并发量极低的场景(如财务对账、审计日志写入)。
二、MySQL与PostgreSQL的默认隔离级别
-
MySQL:默认隔离级别为 可重复读(RR)。
(注:InnoDB引擎在RR级别通过“间隙锁”+“Next-Key Lock”进一步解决了幻读,使RR的实际表现接近串行化。) -
PostgreSQL:默认隔离级别为 读已提交(RC)。
总结
隔离级别越高,一致性越强,但并发性能越差(锁竞争更激烈)。实际应用中需根据业务对一致性和性能的权衡选择,多数场景使用RC或RR级别。