一、一个经典面试问题

很多数据库面试都会问一个问题:

PostgreSQL 没有 Gap Lock,为什么还能解决幻读?

因为在 MySQL 中,解决幻读需要:

Gap Lock
Next-Key Lock

而 PostgreSQL 完全没有这些锁机制

那 PostgreSQL 是如何解决幻读问题的呢?

答案是:

MVCC + Snapshot Isolation(快照隔离)

 理解这一点,就理解了 PostgreSQL 事务的核心设计。


二、什么是幻读(Phantom Read)

幻读指的是:

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

例如:

事务A:

BEGIN;

SELECT * FROM orders WHERE price > 100;

返回:

id  price
1   120
2   150

此时事务B插入一条记录:

INSERT INTO orders VALUES (3,200);
COMMIT;

事务A再次查询:

SELECT * FROM orders WHERE price > 100;

结果:

id  price
1   120
2   150
3   200

多出一条记录,这就是 幻读


三、MySQL如何解决幻读

MySQL InnoDB 的默认隔离级别是:

REPEATABLE READ

为了防止幻读,MySQL使用:

Next-Key Lock = 行锁 + Gap Lock

例如:

SELECT * FROM orders WHERE price > 100 FOR UPDATE;

数据库会锁住:

(100, +∞)

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

优点:

  • 防止幻读

缺点:

  • 锁范围大

  • 并发性能下降

  • 容易产生锁等待


四、PostgreSQL为什么不需要Gap Lock

PostgreSQL 的核心机制是:

MVCC(Multi-Version Concurrency Control)

每条记录都有 多个版本

row version

例如:

id price xmin xmax
1  120  100  0

字段含义:

字段

含义

xmin

创建该行的事务ID

xmax

删除该行的事务ID

当事务开始时,PostgreSQL 会创建一个:

Snapshot

这个 Snapshot 记录:

当前已提交事务
当前正在运行事务

之后所有查询都会基于这个快照读取数据。


五、Snapshot Isolation如何避免幻读

假设:

事务A开始:

snapshot = 当前数据库状态

查询:

SELECT * FROM orders WHERE price > 100;

返回:

1
2

此时事务B插入:

INSERT INTO orders VALUES (3,200);
COMMIT;

当事务A再次查询:

SELECT * FROM orders WHERE price > 100;

结果仍然是:

1
2

因为:

事务A看到的是事务开始时的快照

而不是当前数据库状态。

所以:

新插入的记录不在snapshot中

因此不会产生幻读。


六、PostgreSQL的Repeatable Read

在 PostgreSQL 中:

Repeatable Read = Snapshot Isolation

特点:

  • 不脏读

  • 不可重复读

  • 不幻读

  • 不需要Gap Lock

这也是 PostgreSQL 并发能力强的重要原因。


七、PostgreSQL Serializable更先进

PostgreSQL 的最高隔离级别是:

Serializable

实现方式:

SSI(Serializable Snapshot Isolation)

核心思想:

  • 不加锁

  • 检测事务冲突

  • 如果冲突则回滚

例如:

ERROR: could not serialize access due to concurrent update

应用程序只需要:

retry transaction

相比 MySQL:

数据库

Serializable实现

PostgreSQL

SSI

MySQL

强制加锁

PostgreSQL 的并发性能明显更好。


八、PostgreSQL事务设计的优势

总结 PostgreSQL 的事务架构:

特性

PostgreSQL

MySQL

MVCC

tuple version

undo log

默认隔离级别

Read Committed

Repeatable Read

幻读解决方式

Snapshot

Gap Lock

Serializable

SSI

强锁

并发性能

PostgreSQL 的设计理念是:

尽量减少锁,提高并发能力。


九、总结

PostgreSQL 不使用 Gap Lock,却能避免幻读,原因是:

MVCC + Snapshot Isolation

事务读取的是:

历史版本

而不是实时数据。

这种设计带来的优势:

  • 减少锁

  • 提高并发

  • 减少死锁

这也是为什么 PostgreSQL 在 高并发系统和数据平台中越来越受欢迎

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐