适合人群:会写基本 CRUD、准备做项目选型或刚接手多数据库项目的 Java 开发者。
先说结论:**没有“最好的数据库”,只有最匹配当前约束的数据库。**普通业务系统优先考虑 MySQL;复杂数据模型、GIS、JSONB 或复杂分析需求突出时重点评估 PostgreSQL;客户既有 Oracle 体系或对企业级治理、高可用有明确要求时使用 Oracle。选型时,现有生态和团队熟悉度通常比“某项参数更高”更重要。
一、先用一张图建立全局认识
MySQL、PostgreSQL(通常简称 PG)和 Oracle 都是关系型数据库:都有表、SQL、索引、事务、锁、备份与高可用方案。它们不是“一个能做、另一个不能做”的简单关系,真正不同的是设计优先级、默认行为和生态成熟的方向。
把它们想成三种不同取舍的工具:
- MySQL:把常见 Web 业务做得足够成熟、足够普及。以 InnoDB 为默认引擎后,事务、行锁、MVCC 都已经是标准能力;资料、云服务、招聘市场和运维工具也最丰富。
- PostgreSQL:更强调 SQL 标准、丰富的数据类型与可扩展性。除了关系数据,还常被用于 JSON 文档、全文检索、空间数据(PostGIS)及复杂报表等场景。
- Oracle Database:长期服务于金融、电信、政务等关键系统,企业级权限、审计、备份恢复和高可用产品线成熟;相应地,采购、许可和专业运维的门槛也更高。
不要把“开源”理解成“没有成本”。数据库的总成本还包括迁移、备份恢复、监控、故障演练、性能调优和团队学习。反过来也不要因为 Oracle 功能强大,就在一个普通后台管理系统里引入过重的复杂度。
二、核心差异速查表
| 维度 | MySQL | PostgreSQL(PG) | Oracle Database |
|---|---|---|---|
| 开源 / 授权 | 社区版可用,另有商业支持 | PostgreSQL License,开源 | 商业产品为主,提供 Free / XE 等受限版本 |
| 常见定位 | Web 业务、SaaS、常规 OLTP | 复杂业务、分析、扩展型数据能力 | 关键核心系统、成熟企业 IT 体系 |
| 默认事务引擎 / 内核 | InnoDB | 单一内核 | 单一内核 |
| 默认隔离级别 | REPEATABLE READ |
READ COMMITTED |
READ COMMITTED |
| JSON 能力 | JSON 类型与函数 |
json / jsonb,索引与操作符丰富 |
支持 JSON,企业版本特性随版本变化 |
| 地理空间 | 可用,但通常借助生态方案 | PostGIS 是强项 | 有 Spatial 等企业能力 |
| 全文检索 | FULLTEXT | 内建全文检索、扩展丰富 | Oracle Text 等产品能力 |
| 常用高可用形态 | 主从复制、MGR、InnoDB Cluster | 流复制、逻辑复制、Patroni 等 | Data Guard、RAC 等 |
| 典型学习 / 运维门槛 | 较低 | 中等 | 较高 |
表格用于建立方向感,不用于替代压测。比如“高并发”并不是 MySQL 的专属标签;一张缺少索引的表、一个长事务或错误的分页 SQL,换成任何数据库都会慢。
三、架构概念:同叫“数据库”,层级不完全一样
3.1 MySQL:一个实例下有多个 database
MySQL 常见的使用方式最直观:连接到一个 MySQL 实例,再通过 USE app_db; 进入某个数据库。表名通常写作 app_db.users。
1 | CREATE DATABASE app_db; |
MySQL 中的 database 和 schema 基本可以看成同义词。业务应用经常“一套服务一个库”,不同库之间通过账号权限隔离。
3.2 PostgreSQL:实例、database、schema 三层都要分清
PG 的一个实例可以创建多个 database;每个 database 内还可以建立多个 schema。默认 schema 是 public,对象的完整名字可以是 public.users。
1 | CREATE DATABASE app_db; |
这意味着 PG 的 schema 很适合做同一数据库内的逻辑分区:例如 billing、identity、audit。它不是 MySQL 里“必须新建一个库”才能获得的唯一隔离方式。
3.3 Oracle:用户通常就是 schema
Oracle 的日常开发中,用户与 schema 紧密绑定:frank 用户创建的 users 表属于 frank.users。它没有 MySQL 那种通过 USE 切换当前库的工作流。
1 | CREATE USER app_user IDENTIFIED BY "StrongPassword_123" |
这里还会遇到 Oracle 的 CDB / PDB、表空间等概念。刚开始做业务表时无需死记全部存储层级,但要知道:**表逻辑上属于 schema,物理上存放在表空间的数据文件中。**更多入门操作可以读 Oracle 快速入门:15 分钟从安装到增删改查。
四、事务与并发:三者都有 MVCC,别只背概念
MVCC(多版本并发控制)的目标,是让读操作在多数情况下不必阻塞写操作。三者都有这类思想,但版本保存方式、垃圾清理和默认隔离级别不一样。
4.1 默认隔离级别会改变“同一段 SQL”的观察结果
- MySQL InnoDB 默认
REPEATABLE READ:同一个显式事务里的普通快照读,通常会看到同一份一致性视图。针对范围条件的当前读,InnoDB 还可能使用 next-key lock,以降低幻读问题。 - PostgreSQL 默认
READ COMMITTED:每条 SQL 语句在开始时看到一个新快照。因此同一个事务中先后执行两条SELECT,第二条可能看见别的事务刚提交的数据。 - Oracle 默认
READ COMMITTED:同样以语句级一致性读为常见行为;它通过 Undo 信息构造查询所需的历史版本。
下面两段查询都在观察“另一事务已提交更新后,第二次读取是否变化”这一问题,但事务控制语法要分开写:
1 | -- MySQL / PostgreSQL:显式事务 |
在 MySQL 默认的 InnoDB REPEATABLE READ 下,两个普通快照读通常保持一致;在 PG、Oracle 默认 READ COMMITTED 下,第二条语句可能读到新值。需要锁定当前记录并修改时,明确写出 SELECT ... FOR UPDATE,并让事务尽量短。
4.2 三个容易被忽略的运维点
- MySQL:长事务会让 Undo Log 不能及时清理,还会放大锁等待;范围更新前要确认索引,避免锁住远多于预期的记录。
- PostgreSQL:更新会创建新的行版本,旧版本需由 VACUUM 回收。长事务会阻碍清理,最终可能导致表膨胀,因此要监控 autovacuum 和最老事务。
- Oracle:Undo 表空间既服务回滚也服务一致性读。长查询与大量更新并存时,应关注 Undo 的容量和保留策略,避免历史版本不足。
这些不是“某数据库有缺陷”,而是 MVCC 为了减少读写互相等待所付出的存储和清理成本。
五、最常碰到的 SQL 方言对照
应用层若使用 MyBatis、JPA 或 jOOQ,仍然需要知道这些差异。ORM 能减少重复代码,不能抹掉分页、自增、日期函数和锁语义的差异。
5.1 自增主键
1 | -- MySQL |
老版本 Oracle 常见的写法是 SEQUENCE + TRIGGER,不要看到它就误以为项目写错了;只是新版本已经可以直接使用 IDENTITY。
5.2 分页
1 | -- MySQL |
OFFSET 越大,数据库跳过的记录越多。列表翻到很后面时,三者都更建议改成游标 / Keyset 分页:记录上一页最后一条的有序字段,再继续向后查。
1 | -- 三者都容易迁移的思路:取下一页,而不是跳过 N 行 |
注意:MySQL / PG 也支持 FETCH FIRST 的版本与兼容性要按实际数据库确认;要追求跨库稳定,分页 SQL 通常交给方言层生成。
5.3 空值、字符串拼接和当前时间
| 目的 | MySQL | PostgreSQL | Oracle |
|---|---|---|---|
| 判空替换 | IFNULL(a, b) |
COALESCE(a, b) |
NVL(a, b) 或 COALESCE(a, b) |
| 字符串拼接 | CONCAT(a, b) |
a || b |
a || b |
| 当前时间 | NOW() |
CURRENT_TIMESTAMP / NOW() |
SYSDATE / SYSTIMESTAMP |
| 日期格式化 | DATE_FORMAT(t, fmt) |
TO_CHAR(t, fmt) |
TO_CHAR(t, fmt) |
COALESCE 是标准 SQL,能用时更利于跨库迁移。还要特别留意:Oracle 将空字符串 '' 视为 NULL,而 MySQL、PG 不这么处理;表单字段迁移到 Oracle 时,这会影响唯一约束、判空条件和业务校验。
5.4 插入冲突时更新(Upsert)
1 | -- MySQL |
MySQL 8.0.20+ 对 VALUES(col) 在 ON DUPLICATE KEY UPDATE 中有弃用提示,生产项目可改用插入行别名;而不同数据库的冲突条件、并发细节也不相同。不要把 Upsert 当成“天然幂等”,仍需为业务唯一键设计正确的唯一约束。
5.5 标识符与 DDL 事务
- 标识符大小写:PG 和 Oracle 未加双引号的标识符会分别折叠为小写、大写;一旦加双引号,就必须以后完全匹配大小写。团队最稳妥的约定是:表名、字段名统一小写下划线,不要随意加双引号。
- DDL 能否回滚:PG 的大量 DDL 可以放在事务内回滚;MySQL 许多 DDL 会隐式提交;Oracle 的 DDL 会隐式提交当前事务。上线迁移脚本不能只凭“开发环境执行成功”判断可回滚性。
六、数据类型与扩展:PG 经常在这一项胜出
6.1 JSON:不是存进去就结束
三者都能存 JSON,但表达力不同:
- MySQL 的
JSON适合在关系表中保存少量变化快的扩展属性,并配合生成列或函数索引优化热点字段。 - PG 的
jsonb会以二进制形式处理,配合 GIN 索引和丰富操作符,特别适合需要按 JSON 内部结构检索的场景。 - Oracle 也支持 JSON 相关类型与函数,但具体能力与许可证要按数据库版本、部署形态核对。
无论选谁,关键条件仍要优先建成普通列并建立合适索引。把所有字段都塞进 JSON,只会把关系型数据库变成难维护的“半文档库”。
6.2 复杂数据能力
PG 常被选中的原因还包括:ARRAY、范围类型、枚举、窗口函数、CTE、物化视图,以及 PostGIS。它们让某些本该拆到多个中间服务或额外产品的需求,可以先在一个数据库中可靠完成。
MySQL 与 Oracle 也有各自的空间、全文检索、分析函数和分区能力。区别不在于“能不能写”,而在于项目是否需要这类能力作为主要竞争力,以及团队是否能把它们长期运维好。
七、实际项目到底怎么选?
先判断不可谈判的硬约束,再看最核心的负载和团队能力,而不是先挑一个数据库再为它找理由。
优先选 MySQL 的情况
- 新建的后台、内容、电商、订单、SaaS 等常规 Web 业务;
- 团队现有监控、备份、分库分表、读写分离体系围绕 MySQL;
- 当前核心是稳定完成 OLTP,而不是复杂数据计算;
- 需要快速招聘、交接,或希望从大量社区经验中直接受益。
建议阅读 MySQL 从零到一(01):数据库与 SQL 基础,再继续学习事务、索引和慢 SQL。数据库性能的第一生产力始终是正确的模型和索引,而非换产品。
优先评估 PostgreSQL 的情况
- 业务依赖复杂查询、窗口分析、CTE、全文搜索,或需要丰富的可扩展类型;
- 有明确的地理空间需求,计划使用 PostGIS;
- JSON 内部查询很多,且不想为每项检索再同步一套搜索系统;
- 团队愿意掌握执行计划、索引类型、VACUUM 和复制等 PG 运维要点。
“PG 功能更多”并不自动代表应当选 PG。若团队完全没有经验、需求又只是用户表和订单表,MySQL 往往是更经济的起点。
继续使用或选用 Oracle 的情况
- 客户、行业规范或现有核心系统已经明确要求 Oracle;
- 对审计、权限、高可用、容灾和商业支持有严格采购与合规要求;
- 团队已有 DBA、备份恢复流程和成熟的 Oracle 运维体系;
- 迁移成本和兼容性风险远高于许可成本。
新项目如果只是因为“Oracle 更专业”而引入它,先把许可、版本、容器/云部署限制、备份演练和 DBA 能力写入项目预算。技术选型需要计算全生命周期成本。
八、那 SQL Server、SQLite、MariaDB 呢?
本文重点比较最常见的三种,但实际工作还会遇到:
| 数据库 | 更适合什么场景 | 一句话提醒 |
|---|---|---|
| SQL Server | .NET / Microsoft 技术栈、企业 BI 与 Windows 生态 | 工具链和企业集成强,Linux 与容器支持也已成熟 |
| SQLite | 移动端、桌面端、嵌入式、单机工具、测试 | 它是文件级数据库,不是替代高并发服务端数据库的方案 |
| MariaDB | 希望保留 MySQL 使用体验与开源路线的团队 | 与 MySQL 不是永久“完全兼容”,版本功能要逐项核对 |
| Redis / Elasticsearch | 缓存、排行榜、搜索等特定能力 | 多数情况下是关系型数据库的补充,不是直接替换 |
九、上线前的选型自查清单
在技术评审会上,把下面问题写成答案,而不是只写一个数据库名字:
- 客户、已有系统、云产品或合规条款是否已经指定数据库?
- 未来一年最主要的读写模型是什么:点查、事务写入、复杂报表、全文搜索还是地理查询?
- 需要哪些高可用指标:RPO、RTO、异地容灾、演练频率?
- 团队是否真的能做备份恢复演练、慢 SQL 分析、复制故障切换?
- 数据量增长后,分区、归档、冷热分离的路径是什么?
- 应用框架、驱动、迁移工具、BI 工具是否都兼容目标版本?
- 许可、云实例、商业支持和人力成本,三年合计是多少?
- 如果未来要迁移,SQL 方言、数据类型和存储过程会把你锁定到什么程度?
十、总结
- MySQL:常规 Web OLTP 的可靠默认选项,生态和人才最普及。
- PostgreSQL:当复杂 SQL、丰富类型、JSONB、GIS 或扩展能力是真实需求时,值得优先评估。
- Oracle:适合已有 Oracle 生态及对企业治理、关键业务连续性要求极高的场景,但要接受更高的许可和运维投入。
- 三者都有事务、索引、MVCC 和高可用方案;真正决定稳定性的,往往是模型、索引、事务边界、备份演练和团队经验。
- 选型不是数据库能力排行,而是硬约束、主负载、团队能力和总成本的平衡。