漫谈 Oracle 兼容
做数据库产品有很多种可能的做法N种套路。不管是完全从头开始,还是站在巨人的肩膀上演化都是 一件投入巨大的事情。只要是真刀实枪而不是逢场作戏,都注定了是一场持久战。做产品显 然不只有兼容现在的霸主 Oracle 一条路,但为什么很多产品做着做着做着就走上了这条道呢? 本文无法回答这个问题,但试图从技术角度对 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 兼容的目标不是一个固定靶,而是一个移动靶。以目前比较流行的 Oracle 12c 版本为例,它的功能 极为庞大,比早期的 Oracle 5 要复杂 N 多倍。例如它支持的主要功能包括Oracle documents:
- 符合 SQL:2011 核心级
- 多租户
- RAC
- Data Guard
- 备份和恢复
- 在线对象重建
- FLASHBACK
- 自动负载管理
- 结果集等缓存
- 内存引擎
- 安全、加密和审计
- 存储过程(SQLJ、.NET)
- 各种工具(管理、调优、测试等)
- 分区表
- OLAP
- 压缩
- 并行处理
- 数据复制
- 全文索引
- 空间数据
- XML等等
兼容,更大的挑战还在于围绕 Oracle 的生态。做到什么程度的兼容才能让整个生态中的多 数软件可以不修改而很好的工作?例如各种 ERP、CRM、GIS 软件?各种数据库中间件、ETL? 更不用说各种五花八门的应用平台了。为了认识清楚这个问题,有必要对兼容做一些定义。
- 100% 兼容,应用程序一行代码都不改?
- 实现了的功能尽量兼容,应用程序尽量少改?
- 做语法或函数之类浅层次的兼容,走到哪算哪?
显然,100% 兼容是不可能的事情。务实的态度只能是实现核心的功能,并且尽量保持兼容; 万一应用用到了还没有实现的功能,那就必须要改写。万一功能还有一些地方不兼容,应用 也必须要修改。涉及到第三方独立软件供应商的地方,例如 GIS、ERP、报表之类的,实际 上也基本上宣告了无法兼容。
Oracle 兼容的难点
如果我们重点关注功能,而暂时忽略性能、可靠性、可维护性、服务、平台兼容、合规等之 外;除了前面列出的核心功能之外,也还有大量的细节需要决定是否兼容。在罗列一些常见 的功能点之前,我们先看几个会影响系统的“小”技术点。
“小”技术点
-
对象名的大小写
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 等,还是用每个产品自己的系统表或视图?
下面简单罗列了一些基本功能点:
- 用户和角色
- 名字空间(库/模式/对象)
- 对象名的大小写
- 字符集
- 数据类型
- NULL 语义
- SQL 函数
- 存储过程
- PACKAGE
- 触发器
- SQL语法和语义
- 数据字典
- 数据迁移
数据访问接口
数据访问接口是应用程序访问数据库的通道。它与编程语言密切相关,可以大致认为一种 语言需要有一种对应的接口。那么问题来了,Oracle 有一大堆数据访问接口,要不要都做 一遍,要不要都做得和它一样?
常用的数据访问接口如下:
- OCI(C语言接口)
- OCCI(C++)
- ODBC(C)
- JDBC(Java)
- OLE DB(C++)
- .NET(C#)
- Python
- PHP
- PRO*C/C++/ADA/COBOL
还有一个隐藏在数据访问接口后面的核心功能:通讯协议。如果不实现类似 Oracle 的通讯 协议,很多功能就实现不了或很低效。CLONE 一个 Oracle 协议不仅需要细致的反向工程, 又有侵权的风险。
工具
Oracle 的开发工具非常丰富,早期版本就有了 SQL*FORMS、SQL Developer 等。这里列出 几个供参考。更多的工具请参考 Oracle 网站 developer-tools。
- Enterprise Manager
- Application Testing Suite
- SQL Developer (IDE)
总结
通过本文,希望能够说明清楚以下几个要点。
- 我所知道的 Oracle 兼容的历史。
- Oracle 兼容的重点和难点。
有了这些背景知识,对于数据库系统的设计者,希望可以在判断是否做 Oracle 兼容以及 如何做 Oracle 兼容的问题上有一些启示;对于数据库系统的应用者,则希望可以协助判断 哪些数据库产品在 Oracle 兼容方面是否可以满足业务的需求。数据库系统设计、数据库 应用都是非常专业的领域,这一篇短文不可能将多数问题都阐述清楚,希望可以起到抛转 引玉的作用。
Oracle
]