本首首发于2018年。
作者:陈萌萌(酒满),OceanBase资深技术专家
相信很多人对我们的了解是从OceanBase作为蚂蚁金服核心系统的数据库开始的,也逐步了解到OceanBase的高可用、高性能等诸多特性。今天我们想通过传统数据库的视角来给大家分享OceanBase的另外一个特性——Oracle兼容性,希望大家能够换一个角度了解OceanBase为用户提供的能力。
Oracle兼容模式
今天,真正对数据库要求比较高的一些行业,像银行、基金、保险等企业其实到现在为止还没有完全摆脱对Oracle的依赖。阿里去IOE比较成功,但我们其实也是经历一个很长的过程才摆脱了对Oracle的依赖。
一则有趣的新闻
让我们从一则新闻开始我们今天的分享。这则新闻相信很多朋友前段时间已经注意到了,就是亚马逊由于使用其自主研发的Aurora PostgreSQL数据库来替换其内部的Oracle系统,造成了Prime Day促销日的一个故障。具体的故障分析据说有25页之多,但是并没有对外公开。
这里我们为大家截取了两句有意思的话。
第一句话来自于亚马逊工程师——“Oracle和Aurora PostgreSQL是两种不同的[数据库]技术,处理“保存点”(savepoint)的方式不一样”。仅凭这一句话,我们似乎无法明确肯定问题的根源,但可以肯定的是,故障是由新引入的Aurora PostgreSQL数据库造成的。
而第二句话就更有意思了,在我个人看来甚至有点强词夺理——“AWS Aurora是为前瞻性应用软件设计的,而Oracle是为较传统的应用软件设计的”。我觉得这不能称其为一个理由,更像是一个借口。不能说你的系统做了面向未来的设计就可以忽略当下对用户的支持和保障,也不能简单粗暴的把用户区分为前瞻性的和传统的,简而言之,所有用户的需求都应该被充分重视。
对照上一条新闻,再来看下面一条新闻,相信大家已经不陌生了,就是从去年(2017年)开始,蚂蚁金服100%的核心系统都开始运行在OceanBase之上,而且OceanBase作为中国自研的数据库创造了突破世界纪录的性能指标。相信大家能够感知到我们的团队做到这一点有多么的不容易。但在这里并不是想表达,我们做的就一定比亚马逊好,其实亚马逊踩过的坑我们在内部都经历过。
这里想说的其实是蚂蚁金服之所以能够成功去掉Oracle,背后是很多人、很多团队的合作和付出。比如,除了OceanBase以外,我们的用户也需要配合我们去做应用改造,大家知道我们的产品目前已经高度兼容MySQL,但Oracle和MySQL毕竟是两个数据库,Oracle用户需要根据我们的语法和功能(也就是MySQL)做大量的改造。
另外一方面,我们还有全世界最好的数据库运维团队,他们也花费了大量的努力去解决由两种不同的数据库所带来的各种各样的麻烦和问题。总而言之,不管我们性能、稳定性做得如何好,只要用户需要从一种数据库迁移到另外一种数据库,开发、运维、用户就要付出大量的努力去解决数据库差异引入的各种问题,付出很大的代价。这也就解释了我们今天为什么要做Oracle兼容性——目的很简单,就是为了最大程度降低用户的迁移及使用成本,这与优化性能、降低运行成本本质上没有区别,都是为了提供更大的客户价值。
经过几年的数据库升级,我们理解的数据库兼容性从方法论上大致可以包括以下这么几个层次:
- 第一是数据层,原生的数据类型是否100%兼容是非常重要的,这里面有个错觉——是不是我们的数据类型范围是Oracle的类型范围的超集就够了?其实不然,很多时候用户依赖这个范围,去检查输入数据的合理性,捕捉错误,因此我们必须做到与原生类型完全一致。
- 第二个是功能,这个很好理解,所有的SQL功能、语法、包括错误码等,都会直接影响到用户程序的可用性,这里面需要投入大量细致的工作,比如,数据长度何时可以截断、两种不同的数据类型如何进行比较等等,仅仅通过文档的描述来实现功能的兼容很多时候是不够的。
- 第三个层面是运维和管理,比如,Oracle有大量的原生字典视图、包括很多运维命令,能否做到兼容影响到DBA的学习成本,同时也会影响到外围工具的兼容性。
- 最后一个层面是核心能力,这一点往往是容易被大家忽略的,觉得我们把用户迁过来了,业务切流了,就万事大吉了,其实远不是这样,因为如果做不到Oracle产品的性能和稳定性,用户从使用角度上还是无法做到一样的体验,比如一条SQL如果需要手动改写才能在OceanBase中产生一个合理的执行计划,那业务的改造还不能完全省去。
这是一张OceanBase支持Oracle兼容性的示意图,可以看到,OceanBase的Oracle兼容性模式是租户级的,也就是说,用户可以在同一个集群内同时运行Oracle/MySQL两种不同类型的租户,这样做也是为了进一步降低用户的部署成本。OceanBase从1.0开始就是云数据库架构,支持多租户间的资源隔离和负载均衡,这些能力在引入Oracle兼容模式后都会继续保留。
那么,我们是如何用一个数据库内核来支持两种不同类型的租户的呢?上图给出了示意:在底层(数据层),不同租户的数据都是按照统一的方式进行存储的,元数据是租户间隔离的,元数据以上,我们定义了MySQL和Oracle两套不同的展示视图。
这里面列举了一些OceanBase 2.0会支持的部分Oracle兼容功能:
- 数据类型:支持number、varchar2、timestamp、CLOB…
- SQL层功能:外连接(+)、窗口函数、层次查询、临时表、DB link、外键
- 事务层:隔离级别、flashback、XA
- 内部视图:部分字典视图
- 索引:全局索引、函数索引
- 分区:hash、range、list分区及二级分区组合
- 伪列:rownum、sequence、virtual column等
- 存储过程:循环、复杂数据类型、cursor、异常
- 客户端:JDBC、ObProxy、C客户端
需要指明的是,这个列表还在随着我们收集到的需求而调整,但是几个重要的功能(接下来我们为大家一一解析),包括全局索引、存储过程、基础数据类型等,OceanBase 2.0都一定会支持。
OceanBase 2.0 的新特性
全局索引
全局索引是OceanBase 2.0会发布的一个重要功能,这个功能也是基于2.0的全局一致性的特性而实现的。那么,全局索引解决了哪几个问题呢?
- 多维度扩展性 :这个概念不是我们提出来的,简单来说就是:如果今天你的一张数据表随着数据的快速增长,单机装不下了,你就需要考虑分布式方案,在OceanBase内部是通过分区表这一功能来实现的。但是,如果没有全局索引,分区表只能解决主表的分区和扩展,而主表之外的二级索引就必须被拆分为分区内的局部索引,这样一来从访问性能和维护上就和之前的索引(其实是全局索引)有很大的不同,而实现了全局索引后,之前的二级索引也可以按照任意的方式进行分区,扩展到多机上,整个扩展性就变成很多维的了。
- 跨分区全局唯一索引:唯一索引要求索引对插入的每条数据保持唯一性,如果没有全局唯一索引,那么为了保证唯一性,就会对用户的分区方式增加很多限定条件。
- 强一致:全局索引可以保证强一致性的访问,和用户自己创建一张全局的数据表作为索引相比,提供更好的一致性保障。
- 支持更高效的查询方式:全局索引可以实现真正的全局查找,而不是依赖基于分区键的裁剪定位到数据所在的分区,在少量数据访问时,执行的效率更高。
当然,全局索引也有很多难点,比如一致性的保证,建索引中的异步化考虑等等,是一个实现难度很高的特性。
分区
分区功能是分布式数据库的一个重要能力,我们在MySQL模式上支持了部分分区方式,这些方式都会以Oracle兼容的方式继续提供支持。另外,我们还新增了list分区,这个对于不同值个数比较小的分区场景有非常重要的意义。另外我们还将提供更多的分区管理功能。分区裁剪的能力也会进一步增强。
Sequence
在OceanBase 2.0中,我们将支持sequence对象的使用。作为分布式数据库,我们为了避免全局sequence的热点访问,实现了节点内部的sequence缓存,并通过提前预取sequence范围等一系列优化手段,确保整个系统的可用性和容错能力。
DB link
DB link也是Oracle的一项重要功能。基于DB link,用户可以做跨库的查询和事务,OceanBase 2.0将支持OceanBase集群之间的跨库访问和跨库事务。
存储过程
存储过程是OceanBase 2.0 Oracle兼容性的重要功能。在迁移传统Oracle用户的时候,存储过程一直是横在所有数据库厂商面前的拦路虎。当年我在Oracle参加新人培训的时候,PL/SQL组的一位资深工程师就得意的说,“我们每写一条PL/SQL语句,就在用户的脖子上加了一根锁链”。
事实也的确如此,存储过程的代码往往涉及到很多业务逻辑,几乎没有重构的可能。如果不支持,就只能重写业务逻辑。而且,存储过程在很多场景依然有非常大的不可替代性。例如:
如上图可以看到,交互式的事务处理的超过50%的时间往往消耗在客户端与数据库之间的通信或是客户端的处理时间上,数据库的性能在这种情况下只能通过加大客户端的并发来实现。但是有的场景,简单的增加并发并不能真正提高性能。例如,如果用户在事务开始的时候加了一把行锁,那么整个事务都将处于该锁的“临界区”之内,处理能力直接和事务的延迟有关,这就是典型的“热点行”问题,而有了存储过程,事务的逻辑可以完全在数据库端完成,耗时更短,热点行的处理能力也就更高。
同时,OceanBase 2.0的存储过程是基于LLVM编译执行的,因此在性能上能够提供极致的体验。
客户端驱动——JDBC driver
在客户端驱动上,OceanBase的做法是基于MySQL的通讯协议,进行二次扩展,新的扩展协议在继续支持MySQL协议以外,还将支持Oracle的原生数据类型。
内核全面升级
刚才我们说了,在兼容Oracle数据库上,功能和表现是一方面,性能和稳定性的要求也是重中之重。OceanBase 2.0对数据库内核进行了全面的升级换代,增加了很多新的功能和特性。
直方图
直方图是优化器优化依赖的重要统计信息的一种。OceanBase 2.0支持了兼容Oracle的等高直方图和频率直方图,可以通过自动或者手动的方式进行收集,并自动根据数据的特征选择合适的采样率,基于直方图信息,我们的优化器将能够生成更为准确的执行计划。
自适应计划匹配
在我们的业务中,经常会遇到所谓“大小账号”问题,即,如果一条查询是查询某个商户的销售记录的,那么查询某个大商户时,势必返回很多记录,而一个小商户的相关记录可能只有几条。在这种情况下,要求我们使用不同的执行计划,为了解决这个问题,在OceanBase 2.0中,引入了自适应计划匹配,其目的是处理同一条SQL不同参数时,可以选择合适的执行计划。基本思路是:通过条件选择率的划分,将整个计划空间按计划进行分割,根据入参的选择率选择恰当的执行计划。
计划演进
执行计划演进是我们为了确保计划稳定性而开发的重要功能,其基本思想是通过真实的流量灰度执行新生成的执行计划,在确保新的计划满足预期后才完成新老计划的替换,这个逻辑大大降低了由优化器自身问题而引入的计划回退的现象。在Oracle18c的发布会上,Larry Ellison也介绍了Oracle中的类似功能,从这点上看,我们和Oracle想到一起去了(甚至比他们还更早一些)。
并行查询优化
并行查询是OceanBase 2.0引入的全新特性。为了配合整个并行查询框架的升级,我们对优化器也做了相应的调整和扩展,支持了更多的优化路径。
Oracle兼容性的工作才刚刚开始,OceanBase 2.0可以说是“万里长征的第一步”,其实很多兼容性的工作到最后拼的都是对细节的掌握和处理。随着基本功能的支持和完善,可以预见,更大的挑战是在整体的用户体验上能否追上甚至超越Oralce。只有做到了这一点,我们才能充满自信的说,我们为用户的平滑迁移铺平了道路。