今年Oracle似乎又火了,火得要下掉,目前中国大概有240+数据库企业,在国产信创的大趋势下,一片欣欣向荣,国库之春已然来临。到今天为止,Oracle依旧是市场份额最大的数据库,天下苦秦久矣,Oracle在国内的这份市场,未来2-3年内注定会被瓜分得必须剩点渣,数据库市场格局也会基本定型。当年如火如荼的上,现在吹枯拉朽的下,小编君有种半夜从被窝里抓起来去扛炸药包的感觉,这么多年下来,去O才刚刚开始。
去O中数据迁移肯定是无法避免的,Oracle数据迁移的复杂度,在小编君接触的所有数据库里,应该算是最高的,庞大的功能对象和数据类型先不说,单就增量/全量数据同步上,就可以出一部专辑。我司的DBMotion数据传输迁移平台已经支持Oracle/MySQL/Mongo/openGauss/PostgreSQL的全系列,就目前中国的市场而言,Oracle和MySQL的需求量还是最大的,我们在支持这两款数据库的过程中也明显感觉,只要深入到细节,真是隔库如隔山。小编在这里列一些具体的技术点,各自体会。
1 增量数据获取
Oracle增量数据获取方式有很多,但实在不能忍受搞一堆的trigger,或者logminer那种蹩脚的dump+查表的方式,我们是直接解析的redo和归档文件,这是一件枯燥的逆向工程,自己组合数据类型,设计各种事务场景, dump分析日志输出,猜测验证日志格式,最终的效果就是速度快,实时性高, 50M/秒的redo量轻松应对,MySQL这块,我们是基于binlog的数据转换,这个文件的结构内容要清晰,精简太多。
2 事务边界
Oracle的redo日志一般是每隔3秒,或者用户commit时候刷到redo文件的,哪怕你不commit,也是有可能写到redo的,所以解析redo文件时,这个事务到底是回滚还是提交,你是不知道的,你得维护事务状态来应对即将到来的提交或回滚,包括大事务的回滚,而MySQL的binlog里面,就只有commit的事务,回滚事务是不记录binlog的,所以你只管往前解就可以,不用处理中间数据,不用考虑回滚。
3 事务的穿插混合
Oracle在10G开始就有了group commit,多个应用会话的事务在redo文件里是相互揉杂在一起的,你去解析的时候会发现,事务A开始了,操作了,下一条数据居然是事务B的,然后又是事务A的,而MySQL的binlog里面,每个事务一定是连成片的,绝对不交叉,排列得干净整齐,所以在事务的处理逻辑上Oracle需要更多的if else和结构设计。
4 列模式还是行模式
在数据库日志里面是存入行还是列?什么意思?就是你更新一行数据的A字段,日志里面是仅仅记录key+A字段的前后映像,还是将整行都记录进去?好像行业惯例里面,MySQL是全rows模式,Oracle基本是列模式,你很难扭转,这样在拼数据的完整映像时,Oracle就特别费劲,有时可能要反查源库。
5 神奇的RAC多日志流顺序
Oracle有种架构,叫RAC,多个节点,每个节点都能读写数据,现在MySQL界的Auroa架构只能实现一写多读,那么问题来了,你需要将多个Oracle RAC节点的日志流进行全局排序,保证数据更新的顺序,这个排序分批进行,不断前推,也要考虑部分节点事务未到达的等待窗口,想一想是不是和Flink多通道的CheckPoint barrier高水位有点相似了?
6 redo日志切换
Oracle的redo文件是固定的,循环覆盖使用,历史日志归档成archive文件,为了增量实时性,我们是直接解析online redo的,但当业务压力激增时,redo会击穿,你正在解析的数据可能会被抹掉,这是需要很精巧的机制去处理归档和redo的文件解析衔接,包括跨redo边界的事务处理,也有很多细节,MySQL的binlog是连续追加的,不存在这些问题。
7 基于rowid的全量抽取分片
在全量数据的抽取上,由于Oracle单表体量较大,需要考虑一些地方特色的加速方式,比如说同样是多线程抽取表数据,充分发挥并行IO的能力,每个线程获取独立的segment数据,自然是最快的,但是Oracle是堆表,根据Primary Key出来的范围数据,物理上不一定是连续的,也就是说IO层面在多线程上会交织影响的,这里有种方法,就是根据伪列rowid来计算分片边界,至少从OS角度,这个分片在物理上是连续且无交集的,pkrange和rowidrange的跑分结果如下,同样的环境,差距还是挺明显:
--fetch数据,并load加载到目标数据库,8并发,fetch size 40000笔
Bigoracle,81920000 rows,35480MBytes,pkrange parallel 8 process, ETL take 812 seconds!!!
Bigoracle,81920000 rows,35480MBytes,rowidrange parallel 8 process, ETL take 602 seconds!!!
--仅仅fetch数据,没有load操作,8并发,fetch size 40000笔
Bigoracle,81920000 rows,35480MBytes,pkrange parallel 8 process, ETL take 333 seconds!!!
Bigoracle,81920000 rows,35480MBytes,rowidrange parallel 8 process, ETL take 167 seconds!!!
rowid伪列的另外一个意义就是你可以认为Oracle所有的表都是有唯一性的,当我们处理MySQL的无主键/唯一键表时,困难就不止多了一点点。
以上只是Oracle迁移的冰山一角,可以看出,要高效处理Oracle的数据迁移,工程复杂度是挺高的。我们当初是先做的Oracle,大概花了1年多的时间,后面才做的MySQL,感觉如进了天堂一般,增量日志对接三个星期就拿下了,没任何悬念。当然解析出来的数据如何应用到目标端,同构异构,又是另外回事了。目前,我们会支持两种模式,一种是支持主流数据库的端到端;另一种是对接Kafka,设定好标准的数据格式,供下游系统订阅消费。
Oracle的历史包袱是很重的,很多业务开发重度依赖了O的各种特性,如dblink,存过包,分析函数,全局临时表,还有透明加密等等。这些功能不是在下一任里实现,就是到应用开发侧实现。在小编接触的去O中,大致分为3种,1是开发新系统,直接不用O,这是最开心的。2是借着系统重构和升级,将以前一些O系功能改造优化掉。3就是硬替,这种只发生在SQL写的很标准,基本把数据库当存储用的场景,否则没法执行。去O肯定是个持久战,也衷心希望,DBMotion能为去O贡献点绵薄之力!
本文作者:罗春,沃趣科技联合创始人&产品总架构师
Squids(squids.cn)是多云时代的数据库云服务提供商,基于公有云基础资源,提供云上RDS,云备份,云迁移,SQL窗口等企业级数据库服务功能,帮助企业快速构建云上数据库融合生态。