做数据库产品有很多种可能的做法。不管是完全重头开始,还是站在巨人的肩膀上演化都是 一件投入巨大的事情。只要是真刀实枪而不是逢场作戏,都注定了是一场持久战。做产品显 然不只有兼容现在的霸主 Oracle 一条,但为什么很多产品做着做着做着就了这条道呢? 本文无法回答这个问题,但试图从技术角度对 Oracle 兼容这个问题做一些探讨。
据我所知,国内做数据库产品的团队有很多主动或被动选择了 Oracle 兼容的道。最早的 尝试可以追溯到电子工业部支持的国产基础软硬件平台项目 COSA。我不记得那时候选择兼 容/类似 Oracle 的原因,但确实用过其中的 COBASE 数据库,也阅读和修改过其中的一些 代码。COBASE 可以认为是国产数据库最初的尝试,它可以运行在 COSIX 操作系统上。前者 看起来就像一个 Unix 上的 Oracle,后者看起来就像一个 Unix。我不记得 COSIX 是否有 自己的 X Windows 界面或类似的 GUI,但 COBASE 有基于 Curses 的文本化图形界面 (TUI),也有个长得很像 SQL*PLUS 的命令行工具。COBASE 的代码当然是项目参与 机构自己开发的,内核设计跟 Oracle 也不一样,更像一个经典的教科书级的设计。
在随后几年的快速发展中,Oracle 将主要的几个竞争对手远远甩在了身后,其本身的功能 越来越丰富,生态越来越强大。从的角度看,任何一个后来者都不可能通过兼容的设计 追赶上巨人的步伐了。然而,在各种巧合下,还是有很多团队选择了做通用数据库的道 ,并因为其面对的市场需求而进一步选择了 Oracle 兼容的道。如果说当时选择这条道 还有活下去的希望,这也不算是。毕竟稍晚的时候,国际上也有 EnterpriseDB、 DB2 在做类似的事情。历史的潮流很快就被 NoSQL、NewSQL、Spanner、梦到找不到回家的路Aurora 占据,但 国际形势波谲云诡,就连 MariaDB 都要搞搞 Oracle 兼容了。
Oracle 等高手在对决的时候,国内的小弟们还在蹒跚前行;而另一支重要的数据库力量正在 蓬勃发展:以 MySQL 和 PostgreSQL 为代表的开源数据库正从市场的低端开始进步。值得 注意的是,这两个产品在快速发展过程中并没有明确宣传要兼容 Oracle。不过实际上, PostgreSQL 出身名门正派,要比 MySQL 更类似 Oracle 一点。这也是为什么包括 EDB 在 内的一些公司选择了它为基础来做 Oracle 兼容,还拉来了 DB2 做战友。
兼容,这是 IT 行业中比较常见的做法。早到大型机年代,就有不少兼容机厂商,当时活得 也还可以,不过需要注意的是,等兼容机的玩家都差不多死光了,大型机还是 IBM 的一个重要 收入来源。类似的,AMD 等兼容 x86 的公司一直生活在 Intel 的阴影之下,我怀疑没有反 垄断的,它们也早都该关门了。从历史事件中可以推断,靠兼容打败 Oracle 是胜算极低 的事件,能够打败 Oracle 的看来只有时间。
Oracle 兼容的目标不是一个固定靶,而是一个移动靶。以 Oracle 12 为例,它的功能 极为庞大,比早期的 Oracle 5 要复杂 N 多倍。例如它支持的主要功能包括Oracle documents:
兼容,更大的挑战还在于围绕 Oracle 的生态。做到什么程度的兼容才能让整个生态中的多 数软件可以不修改而很好的工作?例如各种 ERP、CRM、GIS 软件?各种数据库中间件、ETL? 更不用说各种五花八门的应用平台了。为了认识清楚这个问题,有必要对兼容做一些定义。
显然,100% 兼容是不可能的事情。务实的态度只能是实现核心的功能,并且尽量保持兼容; 万一应用用到了还没有实现的功能,那就必须要改写。万一功能还有一些地方不兼容,应用 也必须要修改。涉及到第三方软件供应商的地方,例如 GIS、ERP、报表之类的,实际 上也基本上宣告了无法兼容。
如果我们重点关注功能,而暂时忽略性能、可靠性、可性、服务、平台兼容、合规等之 外;除了前面列出的核心功能之外,也还有大量的细节需要决定是否兼容。在罗列一些常见 的功能点之前,我们先看几个会影响系统的“小”技术点。
对象名的大小写 Oracle 的对象名默认都用大写存在系统表中,如果一个产品跟它不一样,要不要改?
表达式的计算 在涉及到数据类型转换、舍入、精度/标度、甚至表达式的求值顺序等问题时,要不要完 全一样?
数据类型的值域 典型的如精确数类型的取值范围;字符型、大对象类型的最大长度(字节数或字符数)等等。
系统的错误码 虽然 SQL 标准定义了很多错误码和 SQLSTATE,而且希望大家用 SQLSTATE。在 Oracle 的世界里,大家更喜欢用 Oracle 定义的错误码,而且很多软件不知不觉的依赖了某些 错误码。要不要把系统的错误码也搞得和 Oracle 一样?
系统的 Bug 应用有时会遇到有些 Oracle 的 Bug,并且采取了一些 Workaround,为了保持兼容,是 不是要做出一个一模一样的 Bug?
事务的隔离级别 众所周知,Oracle 提供了两个隔离级别:读已提交和快照隔离。虽然很多系统也实现了 同名的隔离级别,但是实际的表现却大相径庭。要完全兼容就必须在内核设计上尽量贴 近 Oracle 的做法。
存储过程 Oracle 的设计中大量采用存储过程(PL/SQL)来完成内核之外的功能;应用也大量采用 现成的 PACKAGE 来完成业务逻辑。此外,Oracle 内置支持的还有 Java、.NET 等。
从直觉上看,基本功能应该都已经被标准化了。很不幸的是,SQL 标准的世界并不是这样的。 所以,每个数据库产品在基本概念上就有比较明显的区别。例如权限是用用户和组,还是用 户和角色?SCHEMA 类似于 DATABASE 还是别的?数据字典应该用标准定义的 INFORMATION_SCHEMA 等,还是用每个产品自己的?
数据访问接口是应用程序访问数据库的通道。它与编程语言密切相关,可以大致认为一种 语言需要有一种对应的接口。那么问题来了,Oracle 有一大堆数据访问接口,要不要都做 一遍,要不要都做得和它一样?
还有一个隐藏在数据访问接口后面的核心功能:通讯协议。如果不实现类似 Oracle 的通讯 协议,很多功能就实现不了或很低效。CLONE 一个 Oracle 协议不仅需要细致的反向工程, 又有侵权的风险。
有了这些背景知识,对于数据库系统的设计者,希望可以在判断是否做 Oracle 兼容以及 如何做 Oracle 兼容的问题上有一些;对于数据库系统的应用者,则希望可以协助判断 哪些数据库产品在 Oracle 兼容方面是否可以满足业务的需求。数据库系统设计、数据库 应用都常专业的领域,这一篇短文不可能将多数问题都阐述清楚,希望可以起到抛转 引玉的作用。