PostgreSQL 为什么没有 Gap Lock,却依然能解决幻读?(深度解析MVCC机制)
理解这一点,就理解了 PostgreSQL 事务的核心设计。这也是 PostgreSQL 并发能力强的重要原因。那 PostgreSQL 是如何解决幻读问题的呢?PostgreSQL 的并发性能明显更好。这也是为什么 PostgreSQL 在。之后所有查询都会基于这个快照读取数据。这样其他事务就无法插入新的记录。而 PostgreSQL。
一、一个经典面试问题
很多数据库面试都会问一个问题:
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 在 高并发系统和数据平台中越来越受欢迎。
更多推荐
所有评论(0)