PostgreSQL MVCC
Multiversion Concurrency Control
This means that each SQL statement sees a snapshot of data (a database version) as it was some time ago, regardless of the current state of the underlying data. This prevents statements from viewing inconsistent data produced by concurrent transactions performing updates on the same data rows, providing transaction isolation for each database session.
——PostgreSQL 18.4 Documentation
PostgreSQL的MVCC模型采用了数据快照机制,每一条SQL语句都有属于自己的一份数据快照,这无关乎底层数据真实情况,意味着PostgreSQL进行查询时不会读到其他事务未提交的脏数据(脏读)。由于快照机制存在的原因,数据库读写锁不会冲突,不存在等待写锁释放读锁获取的情况,性能会更可观,同时,PostgreSQL的数据库事务隔离级别也与标准数据库事务隔离级别有所不同。
Transaction Isolation Levels
标准数据库事务隔离级别:
| Isolation Level | Dirty Read | Nonrepeatable Read | Phantom Read | Serialization Anomaly |
|---|---|---|---|---|
| Read uncommitted | ✅ | ✅ | ✅ | ✅ |
| Read committed | ✗ | ✅ | ✅ | ✅ |
| Repeatable read | ✗ | ✗ | ✅ | ✅ |
| Serializable | ✗ | ✗ | ✗ | ✗ |
PostgreSQL的数据库事务隔离级别:
| Isolation Level | Dirty Read | Nonrepeatable Read | Phantom Read | Serialization Anomaly |
|---|---|---|---|---|
| Read uncommitted | ✗ | ✅ | ✅ | ✅ |
| Read committed ( Default ) | ✗ | ✅ | ✅ | ✅ |
| Repeatable read | ✗ | ✗ | ✗ | ✅ |
| Serializable | ✗ | ✗ | ✗ | ✗ |
得益于快照机制,PostgreSQL的Read uncommitted isolation level不会产生脏读,Repeatable read solation level也不会产生幻读。
不难发现,标准数据库事务隔离级别有四级,但PostgreSQL的数据库事务隔离级别严格来讲只有三级,Read uncommitted isolation level与Read committed isolation level隔离级别的表现是相同的,但由于标准数据库事务四级隔离级别是业界规范,MVCC模型为适配标准数据库的四级隔离级别迫不得已保留了四级隔离级别,实际只有三级。
Read Committed Isolation Level
A SELECT query sees a snapshot of the database as of the instant the query begins to run.
当执行SELECT读语句时,会在查询准备开始执行的瞬间获取数据库快照。因此在语句执行期间,其他事务未提交的数据或已提交的数据对此语句均不可见,值得注意的是:
- 在同一事务内,
SELECT语句可以读到此事务内其他语句执行的数据更改,即使这些更改仍未提交。 - 在同一事务内,两条
SELECT语句读取结果也许不同,因为在第一条SELECT语句执行完毕之后第二条SELECT语句执行之前,可能会有其他并发事务提交了数据更改。
当执行UPDATE、DELETE写语句时,它们在查找特定行阶段的表现与SELECT语句表现相同,在写操作执行前,会将快照与表数据比对




