MySQL 与 PostgreSQL 的事务与并发差异

对比 MySQL InnoDB 与 PostgreSQL 在事务、MVCC、隔离级别、锁与恢复日志上的差异,帮助把相同术语还原到具体产品实现。

#type / synthesis #status / growing #tech / dev / backend #resource / mysql #resource / postgresql

[!info] related notes

MySQL 与 PostgreSQL 的事务与并发差异

范围

这篇聚焦 MySQL InnoDB 和 PostgreSQL 在事务落地、并发控制与恢复链路上的差异,不展开复制拓扑、高可用架构和运维参数细节。

为什么要放在一起理解

初学时最容易误以为:

  • SQL 一样,事务行为就一样
  • 都说支持 ACID 和 MVCC,所以差异只是语法层面

但在真实系统里,往往正是实现差异决定了这些现象:

  • 为什么同一段业务代码在两个数据库上的默认行为不同
  • 为什么一个数据库更容易出现范围锁等待,另一个更容易让你遇到序列化失败或版本可见性问题
  • 为什么讨论日志时,有人说 WAL,有人说 Redo / Undo / Binlog

为什么这些差异会同时出现

事务并不是独立组件,它要同时协调:

  • 版本可见性
  • 锁冲突
  • 提交与恢复
  • 默认隔离级别

MySQL InnoDB 和 PostgreSQL 在这些层面的实现路线不同,所以即使表面上都叫“事务”“MVCC”“可重复读”,工程体验也会不一样。

依赖路径 / 调用链 / 演进链

可以从五个层面观察:

  1. 默认隔离级别
  2. MVCC 版本可见性实现
  3. 锁的粒度和范围保护策略
  4. 提交与恢复日志体系
  5. 死锁、冲突与错误表现

对比与易混淆点

维度MySQL InnoDBPostgreSQL关注点
默认隔离级别常见是 REPEATABLE READ常见是 READ COMMITTED同样业务在默认配置下看到的可见性可能不同
MVCC 实现常见通过 [[undo-logUndo Log]] 等机制支撑旧版本更直接依赖行版本与事务可见性信息
锁策略范围更新时更容易出现 gap lock、next-key lock 一类现象更常依赖行级冲突和快照可见性范围查询和范围更新的阻塞感受不同
恢复与日志会同时遇到 [[redo-logRedo Log]]、[[undo-logUndo Log]]、[[binlog
冲突表现更常见锁等待、死锁回滚等直观现象在更强一致场景下也常见序列化失败或重试需求应用层错误处理和重试策略可能不同

一个最常见的误区

很多人会说:

  • MySQL 有锁,PostgreSQL 没那么锁

更准确的说法其实是:

  • 两者都会锁
  • 两者都支持 MVCC
  • 只是它们在“何时更早加锁、范围如何保护、旧版本如何提供、冲突如何暴露”上做了不同实现选择

所以同一个业务在 MySQL 上可能更明显感受到范围锁,在 PostgreSQL 上可能更明显感受到快照语义、可见性和重试要求。

如何把它们和前面几篇概念页对应起来

  • 想理解“事务承诺了什么” -> 先看 事务ACID
  • 想理解“并发时能看到什么” -> 看 事务隔离级别
  • 想理解“为什么读写能少阻塞” -> 看 MVCC
  • 想理解“为什么还会等待和死锁” -> 看 数据库锁
  • 想理解“为什么提交后宕机还能恢复” -> 看 数据库日志

这篇的角色不是重复解释这些概念,而是告诉你:同样一组概念,在 MySQL 和 PostgreSQL 里落地方式并不完全一样。

边界与易混淆点

  • 名称相同不代表实现相同,尤其是 REPEATABLE READ、MVCC 和日志体系。
  • 不能把 PostgreSQL 的 WAL 简单等同于 MySQL 的某一个单独日志;它们的术语切分方式不同。
  • “默认行为差不多”不代表边界场景差不多,范围更新、热点写入和长事务尤其容易暴露差异。
创建于 2026/5/3 更新于 2026/5/27