DeepSeek总结的PostgreSQL 和 MySQL兼容性标准
“开箱即用”:为 PostgreSQL 和 MySQL 衍生品定义兼容性标准
原文地址:https://vyruss.org/blog/fosdem-2026-defining-drop-in-replacement-and-beyond.html
https://vyruss.org/computing/slides/fosdem2026_drop_in_replacement.pdf
作者:Jimmy Angelakos, Daniël van Eeden
FOSDEM 2026 数据库开发者分会
引言:生态系统的繁荣与挑战
开源数据库 PostgreSQL 和 MySQL 的巨大成功催生了一个充满活力的生态系统,众多衍生品纷纷宣称提供“开箱即用的兼容性”。然而,这也带来了用户困惑和品牌稀释的问题,因为衍生品常常与上游版本发生显著分歧。
兼容性并非一个简单的“是/否”问题。即使是同一数据库的不同版本也无法做到 100% 兼容(存在已废弃和新增的功能)。那么,“PostgreSQL 兼容”或“MySQL 兼容”究竟意味着什么?
定义兼容性:用户视角
从用户角度看,兼容性意味着几个核心问题:
- 我的应用程序能否与此数据库协同工作?
- 我可以使用哪些数据库驱动程序和 API?
- 我能否与此数据库进行双向复制?
- 云数据库即服务(DBaaS)产品能否提供相同的体验?
- 我能否复用现有的工具和驱动程序生态系统?
两种视角:PostgreSQL 标准与 MySQL 实现
兼容性的探讨通常从两个主要数据库出发:
- PostgreSQL 标准:强调协议、行为、工具链的严格一致性。
- MySQL 实现:更多关注语法的兼容性和协议的遵循,允许在存储引擎、分布式架构等底层实现上进行创新。
PostgreSQL 兼容性框架的建立
在 2025 年 10 月拉脱维亚里加的 PGConf.EU 会议上,成立了一个“建立 PostgreSQL 标准:何为 Postgres 兼容?”的工作小组。其目标是建立一个实用的 PostgreSQL 兼容性标准和测试框架。
随着 PostgreSQL 日益成为企业的“新 Linux”,这项工作变得愈发重要。为什么不仅仅是遵循 ISO SQL 标准?因为 SQL 标准并未定义:
- 索引、磁盘数据格式等实现细节。
- 未标准化功能(如向量搜索、UUIDv7)的函数名。
- 管理命令。
- 网络协议。
里加共识:从二元认证到兼容性矩阵
工作重心已从二元的“通过/失败”认证转向更精细的兼容性矩阵:
- 加权检查清单:区分核心(必需)与可选功能,避免扼杀创新。
- 托管环境例外:针对受管环境(受限的超户权限、文件系统访问)制定特定例外规则。
- 禁止静默失败:例如,
CREATE INDEX必须实际构建索引,而不仅仅是返回“成功”。
核心 SQL 与功能集要求
所有 PostgreSQL 官方文档中“第二部分:SQL 命令”涵盖的内容均为必需项,包括:
- 即使极少使用的功能也必须支持。
- 隐式行为:用户依赖的未文档化行为(如
INSERT ... ORDER BY)。 - 数据类型:
ARRAY、BYTEA、JSONB是必需的。 - 功能依赖:支持触发器意味着必须提供完整的 PL/pgSQL 语言支持。
协议与行为兼容性
- 事务隔离:标准级别(读已提交、可重复读、可序列化)的行为必须完全相同。
- 错误代码:常见错误必须返回相同的 SQLSTATE 代码。
- 系统目录:
pg_catalog必须存在且结构可预测,以确保监控工具正常运行。 - 硬性限制:通常必须匹配 PostgreSQL 的限制(如标识符长度、最大列数)。
连接性与工具兼容性
- 服务器版本字符串:必须满足标准工具(如
psql)的解析要求。 - 标准驱动程序:JDBC、Psycopg 等必须无需修改即可工作。
- 数据迁移:必须支持
pg_dump的导入/导出。 - 执行计划:无需完全相同,但功能结果必须匹配(例如,分区必须能被正确裁剪)。
- 标准工具:必须与 Patroni、pg_basebackup、RepMgr 等工具兼容。
复制兼容性
逻辑复制:
- 必须支持双向复制(产品 X ↔ PostgreSQL)。
- 必须可通过标准复制目录进行观测。
- 供应商的扩展不得破坏与原生 PostgreSQL 的连接。
物理复制:
- 必须支持二进制文件的物理拷贝(或等效方式)。
- 必须支持混合集群(混合使用原生和供应商节点)。
- 必须支持时间点恢复(PITR)和 WAL 访问。
测试框架构想
设想一个位于 PostgreSQL 代码库之外的测试套件,其版本号与 PostgreSQL 发布版本对应。供应商提供兼容的构建目标。测试重点是功能合规性,而非特定的错误——修复一个 PostgreSQL 的错误不应导致测试失败。
兼容性的假象:一个警示案例
考虑一个场景:客户端使用 MySQL 协议连接,执行的却是 PostgreSQL 语法和 SQLite 函数。表面上,它既“理解”MySQL 协议,又能“处理”PostgreSQL 语法。这展示了兼容性的复杂性:
- 这是 MySQL 兼容吗?协议是兼容的。
- 这是 PostgreSQL 兼容吗?语法是兼容的。
这个例子是使用 go-mysql 作为 MySQL 协议代理,后端连接 SQLite 和 PostgreSQL 实现的。试想,如果一个云服务提供商做出类似的事情,会带来多大的混淆?
案例分析:TiDB 的 MySQL 兼容性实践
TiDB 是一个 MySQL 兼容的分布式数据库,其架构选择带来了独特的兼容性挑战与思考:
架构特点:
- 使用 Go 语言编写,并非基于或衍生自 MySQL 代码。
- 使用 TiKV(基于 RocksDB)作为存储层,而非 InnoDB。
- 接受
ENGINE=InnoDB语法但会静默忽略。 - 是一个分布式数据库。
功能兼容性策略:
- 将某些功能(如地理空间和 VECTOR)视为可选。
- 从未实现 XML 数据类型(因为 JSON 更受欢迎)。
- 增加了有用的 MariaDB 特性(如序列)。
- 提出了一个根本性问题:兼容性本身是否应该成为终极目标?
具体挑战
有线协议挑战:
- MySQL 协议 v10 使用能力标志进行功能协商。
- 客户端也使用通告的版本字符串进行功能检测。例如,MySQL Connector/J 在版本 ≥ 8.0 时会查询
information_schema.keywords。当 TiDB 将版本改为8.0.11-TiDB-v7.5.3时,就必须实现这个表。最终,TiDB 不得不分叉 MySQL Connector/J 以支持 TiDB 特定的认证。
SQL 语法与类型摩擦:
- 保留关键字:在不同数据库产品和版本间差异很大。
- EXPLAIN 格式:MySQL 支持多种格式,而 TiDB 使用自己的格式——分布式查询计划在本质上看起来就不同。
- 类型实现分歧:例如,MySQL 有 JSON 类型,而 MariaDB 使用 TEXT 加
JSON_VALID()函数;MySQL 使用UUID_TO_BIN(),而 MariaDB 有 UUID 类型。
二进制日志复制兼容性:
- 转变:从基于语句的复制(SBR)转向基于行的复制(RBR),难以保证副本上结果的完全一致。
- CDC 鸿沟:RBR 是为 MySQL 构建的,而非通用的变更数据捕获(CDC),缺少类型元数据(如是否有符号)。
- 协议漂移:新的
mysql::serialization格式,文档极少,导致与 go-mysql 等工具产生摩擦。 - TiDB 策略:绕过 binlog 生成,对外使用 TiCDC,对内使用数据迁移(DM)工具。
错误、限制与错误重现:
- 错误代码:MySQL 错误包含代码、SQLState 和消息。消息需要完全相同吗?还是只需要代码匹配?TiDB 使用大于 8000 的错误代码以避免冲突。
- 限制:TiDB 默认匹配 MySQL 的限制(如 64 字符的对象名)。
- 错误重现兼容性:MySQL 的
FORMAT()函数在保加利亚语区域设置下存在一个错误。TiDB 是否应该为了保持兼容而重现这个错误?
MariaDB:从“真正开箱即用”到逐渐分化
MariaDB 最初是 MySQL 的真正开箱即用替代品:停止 MySQL,交换二进制文件,启动即可——无需导入/导出。然而,随着时间的推移,MySQL 和 MariaDB 已经在诸多方面显著分化。MySQL 的 SQL 模式历史性地提供了与 Oracle、PostgreSQL 等其他数据库的兼容语法模式,这本身也反映了兼容性的复杂历史。
结论:兼容性是一个光谱,而非终点
“开箱即用”的承诺极具吸引力,但实现真正的兼容性是一项复杂而持续的工作。它涉及协议、语法、语义、行为、工具链和生态系统的多个层面。
无论是 PostgreSQL 阵营正在构建的精细矩阵,还是 MySQL 生态系统中 TiDB、MariaDB 等项目的实践,都表明兼容性应被视为一个动态的、分级的“光谱”,而不是一个非黑即白的静态目标。目标应是让用户的应用程序、工具和技能能够平滑过渡和运行,同时允许数据库在底层架构和新增功能上进行创新。
最终,清晰的沟通、透明的兼容性声明以及由社区驱动的标准测试,对于维护健康的开源数据库生态系统至关重要。
本文地址:https://www.yitenyun.com/6429.html











