PostgreSQL 事务隔离级别详解(以及与MySQL实现差异)

一、什么是事务隔离级别

在数据库中,**事务隔离级别(Transaction Isolation Level)**用于控制多个事务并发执行时的可见性规则。

SQL 标准定义了四种隔离级别:

隔离级别 可能出现的问题
Read Uncommitted 脏读、不可重复读、幻读
Read Committed 不可重复读、幻读
Repeatable Read 幻读
Serializable 无并发问题

常见的并发问题:

1️⃣ 脏读(Dirty Read)

读取到另一个事务 未提交的数据

2️⃣ 不可重复读(Non-repeatable Read)

同一事务内两次读取同一行数据结果不同

3️⃣ 幻读(Phantom Read)

同一事务两次查询 返回的行数不同


二、PostgreSQL支持的隔离级别

PostgreSQL同样支持SQL标准的四种隔离级别,但实际实现略有不同。

隔离级别 PG支持情况 说明
Read Uncommitted 实际等同于RC PG不会出现脏读
Read Committed 默认级别 每条SQL看到已提交数据
Repeatable Read 完整支持 使用Snapshot Isolation
Serializable 完整支持 使用SSI算法

三、Read Committed(默认隔离级别)

PostgreSQL 默认隔离级别是:

复制代码
READ COMMITTED

特点:

  • 每条 SQL 都读取 当前已提交数据

  • 不会脏读

  • 可能出现不可重复读

  • 可能出现幻读

示例

事务A:

复制代码
BEGIN;

SELECT balance FROM account WHERE id = 1;

事务B:

复制代码
UPDATE account SET balance = 200 WHERE id = 1;
COMMIT;

事务A再次查询:

复制代码
SELECT balance FROM account WHERE id = 1;

结果可能变化,这就是 不可重复读。


四、Repeatable Read(可重复读)

在 PostgreSQL 中:

复制代码
REPEATABLE READ

是基于 Snapshot Isolation(快照隔离) 实现的。

事务开始时会创建一个 数据快照(Snapshot):

复制代码
事务开始 → 创建 snapshot
之后所有查询都基于这个 snapshot

特点:

  • 不脏读

  • 不可重复读

  • 不会出现幻读

  • 不需要锁

示例:

复制代码
BEGIN;
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;

SELECT * FROM orders WHERE price > 100;

即使其他事务插入新数据:

复制代码
INSERT INTO orders VALUES (...)

当前事务也 看不到新增数据。

这就是 快照隔离。


五、Serializable(可串行化)

Serializable 是 最高隔离级别。

PostgreSQL 使用:

复制代码
SSI(Serializable Snapshot Isolation)

核心思想:

  • 不加锁

  • 通过检测冲突保证串行执行效果

如果检测到冲突:

复制代码
ERROR: could not serialize access due to concurrent update

此时需要 应用层重试事务。

示例:

复制代码
BEGIN;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

优点:

  • 高并发

  • 不会出现任何并发问题


六、PostgreSQL与MySQL隔离级别实现差异

虽然 PostgreSQL 和 MySQL 都支持相同的隔离级别名称,但实现方式完全不同。

特性 PostgreSQL MySQL(InnoDB)
默认隔离级别 Read Committed Repeatable Read
MVCC实现 tuple version undo log
Repeatable Read Snapshot Isolation MVCC + Gap Lock
Serializable SSI 强制锁
Gap Lock ❌ ✅

七、MySQL为什么需要Gap Lock

MySQL为了防止幻读,需要:

复制代码
Gap Lock
Next-Key Lock

例如:

复制代码
SELECT * FROM user WHERE id > 10 FOR UPDATE;

MySQL会锁:

复制代码
(10, +∞)

这样其他事务无法插入新记录。

缺点:

  • 锁范围大

  • 并发性能下降


八、PostgreSQL为什么没有Gap Lock

PostgreSQL使用:

复制代码
MVCC + Snapshot

事务读取的是:

复制代码
历史版本

因此不需要锁范围来阻止插入。

优势:

  • 并发能力强

  • 不会产生大量锁


九、PostgreSQL为什么没有Read Uncommitted

SQL标准允许:

复制代码
READ UNCOMMITTED

但 PostgreSQL 中:

复制代码
READ UNCOMMITTED == READ COMMITTED

原因是:

PostgreSQL 的 MVCC 架构 天然不允许读取未提交数据。

所以 PG 永远不会出现脏读。


十、查看和设置隔离级别

查看当前隔离级别

复制代码
SHOW transaction_isolation;

输出示例:

复制代码
read committed

设置事务隔离级别

复制代码
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;

或者:

复制代码
BEGIN;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

十一、总结

PostgreSQL 的事务隔离级别总结如下:

隔离级别 脏读 不可重复读 幻读
Read Uncommitted ❌ ✔ ✔
Read Committed ❌ ✔ ✔
Repeatable Read ❌ ❌ ❌
Serializable ❌ ❌ ❌

PostgreSQL 的优势:

  • 强大的 MVCC机制

  • Repeatable Read 无幻读

  • Serializable 使用SSI并发更高

因此 PostgreSQL 在 高并发系统、金融系统、数据平台中非常受欢迎。

相关推荐
ao-weilai几秒前
MySQL数据库:表操作
数据库·mysql·adb
宵时待雨9 分钟前
MySQL数据库1:数据库基础
服务器·数据库·mysql
做运维的阿瑞19 分钟前
一个 NULL 让整列姓名消失?MySQL 字符串与日期函数复盘
数据库·sql·mysql
程序猿乐锅31 分钟前
【黑马点评 | 第十一篇】关注 Feed 流实现
java·数据库·redis·分布式·后端·缓存·maven
phltxy37 分钟前
C 语言文件操作:让数据从内存走向持久化
c语言·网络·数据库
阳光九叶草LXGZXJ1 小时前
达梦数据库-学习-69-DM9主备集群部署
linux·运维·服务器·数据库·sql·学习
jnrjian1 小时前
Connect Microsoft Tools to Oracle Databases powerbi 之类的oracle 客户端
数据库·microsoft·oracle
北京恒星科通刘军1 小时前
灾害监测预警系统中,应急疏散广播的“应急叫应”实际送达率与有效性研究
网络·数据库·人工智能
ShineWinsu1 小时前
对于Redis:List类型的解析
数据库·c++·redis·链表·缓存·面试·list
问商十三载2 小时前
AI引擎生成式优化服务商怎么选?技术核验清单(附脚本)
数据库·人工智能·机器学习