|
为什么你又要处理这个过时的数据库?
并不是我想做。现在中国的这些数据库新贵正在这么做。
? ? ? ? ?
他们想要迁移到新的数据库,他们不能这样做吗?
今年好像又流行了,也快要掉下来了。目前中国约有240多家数据库公司。在国内信息创新的大趋势下,万物欣欣向荣,金库的春天已经到来。截至今天,它仍然是市场份额最大的数据库。长期以来,世界一直在遭受苦难。国内这个市场注定会在未来2-3年内被瓜分,还会剩下一些残渣。数据库市场格局也将基本确定。当年风生水起,如今却已是遍地开花。小编感觉自己就像半夜被人从床上抱起来拎着一包炸药一样。这么多年过去了,去O才刚刚开始。
O中的数据迁移肯定是不可避免的。数据迁移的复杂度应该是小编接触过的所有数据库中最高的。且不说庞大的功能对象和数据类型,单单是增量/全量数据一旦同步,就可以发布一张专辑了。我公司的数据传输迁移平台已支持/MySQL/Mongo//全系列。就目前中国市场而言,MySQL和MySQL的需求量仍然是最大的。我们也清晰的感觉到,在支持这两个数据库的过程中,只要深入到细节,就会有一种隔着一座山的感觉。小编在这里列出了一些具体的技术点供大家体验。
增量数据采集
获取增量数据的方法有很多,但是我实在不忍心做一堆,还是蹩脚的dump+查表的方法。我们直接解析重做和归档文件。这是一项无聊的逆向工程任务。我们需要自己组合数据。类型,设计各种事务场景,dump分析日志输出,猜测并验证日志格式,最终的效果是速度快,实时性高,可以轻松应对50M/秒的重做量。对于MySQL来说,我们是以数据转换为基础的,这个文件的结构和内容应该清晰、精简。
交易边界
重做日志通常每3秒写入一次重做文件,或者当用户写入时。即使不这样做,也有可能写入重做,因此在解析重做文件时,您不知道事务是回滚还是提交。是的,您必须维护事务状态以应对即将到来的提交或回滚,包括大型事务的回滚。在MySQL中,只有事务。回滚事务不会被记录,因此您可以继续前进。 ,无需处理中间数据,无需考虑回滚。
杂事穿插
组从 10G 就已经存在了。多个应用程序会话的事务在重做文件中相互混合。你分析一下就会发现,事务A启动运行后,下一条数据其实是属于事务B的,然后就有了事务A。在MySQL中,每个事务必须连接成一块,绝对不能相交,而且排列得干净利落,所以事务处理逻辑中需要更多的if else和结构设计。
列模式或行模式
行或列是否存储在数据库日志中?有什么意义呢?即当你更新一行数据的字段A时,日志是只记录key+字段A的前后影像,还是记录整行数据?看来按照业界惯例,MySQL是全行模式,基本上就是列模式。它很难改变,因此创建数据的完整图像是非常费力的。有时您可能需要检查源数据库。
神奇的RAC多日志流序列
有一种架构叫RAC,有多个节点。每个节点都可以读取和写入数据。目前MySQL界的Auroa架构只能实现一写多读。那么问题就是需要处理多个RAC节点的日志流。全局排序保证了数据更新的顺序。这种排序是分批进行并持续推进的。还必须考虑某些节点事务未到达的等待窗口。想一想,是不是和Flink的多通道的高水位类似?
重做日志切换
重做文件是固定的并用于循环覆盖。历史日志归档到文件中。为了提高实时性能,我们直接解析重做。然而,当业务压力激增时,redo会崩溃,你正在解析的数据可能会被Erase,需要非常复杂的机制来处理归档和redo之间的文件解析连接,包括跨redo边界的事务处理。还有很多细节。 MySQL是连续追加的,不存在这些问题。
基于rowid的分片全提取
在提取全量数据时,由于单表规模较大,需要考虑一些本地特定的加速方法。比如还采用多线程来提取表数据,充分发挥并行IO的能力。每个线程获取独立的数据。当然,它是最快的,但它是一个堆表。根据Key得到的范围数据,物理上不一定是连续的,这意味着IO层面在多线程上会交织在一起。有一种方法可以根据伪列rowid来计算片段边界。至少从操作系统的角度来看,这个片段在物理上是连续的。并且不存在交集, 和 的跑分结果如下。在相同环境下,差距还是相当明显的:
<p><pre class="code-snippet__js" data-lang="sql"> <code><span class="code-snippet_outer"><span class="code-snippet__comment">--fetch数据,并load加载到目标数据库,8并发,fetch size 40000笔</span></span></code><code><span class="code-snippet_outer">Bigoracle,<span class="code-snippet__number">81920000</span> <span class="code-snippet__keyword">rows</span>,<span class="code-snippet__number">35480</span>MBytes,pkrange parallel <span class="code-snippet__number">8</span> process, ETL take <span class="code-snippet__number">812</span> seconds<span class="code-snippet__operator">!</span><span class="code-snippet__operator">!</span><span class="code-snippet__operator">!</span></span></code><code><span class="code-snippet_outer">Bigoracle,<span class="code-snippet__number">81920000</span> <span class="code-snippet__keyword">rows</span>,<span class="code-snippet__number">35480</span>MBytes,rowidrange parallel <span class="code-snippet__number">8</span> process, ETL take <span class="code-snippet__number">602</span> seconds<span class="code-snippet__operator">!</span><span class="code-snippet__operator">!</span><span class="code-snippet__operator">!</span></span></code><code><span class="code-snippet_outer"><br /></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment">--仅仅fetch数据,没有load操作,8并发,fetch size 40000笔</span></span></code><code><span class="code-snippet_outer"><br /></span></code><code><span class="code-snippet_outer">Bigoracle,<span class="code-snippet__number">81920000</span> <span class="code-snippet__keyword">rows</span>,<span class="code-snippet__number">35480</span>MBytes,pkrange parallel <span class="code-snippet__number">8</span> process, ETL take <span class="code-snippet__number">333</span> seconds<span class="code-snippet__operator">!</span><span class="code-snippet__operator">!</span><span class="code-snippet__operator">!</span></span></code><code><span class="code-snippet_outer">Bigoracle,<span class="code-snippet__number">81920000</span> <span class="code-snippet__keyword">rows</span>,<span class="code-snippet__number">35480</span>MBytes,rowidrange parallel <span class="code-snippet__number">8</span> process, ETL take <span class="code-snippet__number">167</span> seconds<span class="code-snippet__operator">!</span><span class="code-snippet__operator">!</span><span class="code-snippet__operator">!</span></span></code></pre></p>
rowid伪列的另一个含义是你可以认为所有的表都是唯一的。当我们处理MySQL的非主键/唯一键表时,难度就更大了一点。
以上只是迁移的冰山一角。可见,需要高效处理的数据迁移的工程复杂度相当高。我们先做了,花了一年多的时间。然后我们后来就做了MySQL。感觉就像我们在天堂一样。增量日志连接三周就完成了,没有任何悬念。当然,解析出来的数据如何应用到目标端,无论是同构的还是异构的,就是另一回事了。目前我们会支持两种模式,一是支持端到端的主流数据库;二是支持端到端的主流数据库。另一种是连接Kafka,设置标准数据格式供下游系统订阅和消费。
O的历史包袱很重。很多业务开发都非常依赖O的各种功能,比如保存包、分析功能、全局临时表、透明加密等,这些功能要么在下一个版本中实现,要么在应用开发端实现。小编接触过的O去除中,大致分为三种。第一个是不直接使用O来开发一个新系统。这是最幸福的事。二是通过系统改造和升级,对原有O系列的一些功能进行改造和优化。 3是硬替换,只有当SQL写得很标准并且数据库基本用作存储时才会出现,否则无法执行。去O肯定是一场持久战,真心希望自己能为去O贡献一点点力量! |
|