分库分表MyCat 架构迁移 OceanBase | 百丽核心财务系统迁移经验总结与问题汇总
作者:卢文豪,百丽时尚数据库负责人
百丽时尚集团(以下简称百丽)是中国领先的大型时尚鞋服集团,旗下拥有20+ 个鞋服品牌,如#BELLE(百丽)、#TATA(他她)、#TEENMIX(天美意)等,覆盖了从高端到大众时尚、功能、运动、潮流等品类,线下门店共计8000+,覆盖300+城市。作为中国时尚鞋履市场占有率连续十余年位居第一的企业,百丽拥有发达的线下销售网络,从原料到设计到生产,再到终端零售,已形成产供销一体的完整供应链。
在这条供应链背后,由集团的科技中心统筹业务系统的建设与运维,包括零售、库存、财务等核心板块。为了解除底层技术瓶颈对业务发展的影响,科技中心不断迭代技术方案。其中作为核心之一的财务系统刚刚经历了一场“换心脏”手术,将数据库方案从分库分表MyCat 架构迁移到 OceanBase,实现了提性能和降成本的 “双丰收”。
先说成果:性能提升30倍,降本高达原架构的18倍
关键功能效率提升30倍。
以财务系统的成本核算功能为例,整体运行时间相对较长。原本在 MyCat 运行时需耗时 10 小时,迁移至 OceanBase 后仅需 20 分钟,性能提升 30 倍。由监控数据(见图1)可以看出,原系统在每日 02:00–12:00 期间磁盘持续高负载;而在 OceanBase 环境下,相同任务 20 分钟内即可完成,负载迅速回落,提效幅度显著,已得到研发团队的高度认可。

图1 数据库迁移前后性能监控数据
存储成本降96.7%,硬件成本降59.4%。
原来的 MyCat 数据共占用 20.3 TB,迁移至 OceanBase 后仅占用 1.3 TB,整体压缩率高达96.7%。压缩收益主要来自两方面:一方面是 OceanBase 自身的高压缩率,另一方面是原来的 MyCat 架构下存在大量数据冗余,经过 OceanBase 的存算一体化架构整合,冗余数据得到释放。
另外,原来的 MyCat 环境部署共使用 37 台服务器,迁移到 OceanBase 后仅用 10 台服务器即可支撑全部业务,使该业务服务器费用从207万缩减为84万,硬件成本下降59.4%。
之所以能够取得这样的效果,一方面是由于原架构的冗余与性能瓶颈对业务系统产生了限制,而新的数据库方案不仅解开了瓶颈,还带来了更大的增益。另一方面,归结于正确的迁移和技术优化,下文展开叙述我们的迁移经验。
经验汇总:MyCat 切换 OceanBase 三步走
切换背景
百丽的业务系统原本统一采用#MyCat中间件 实现分库分表,以每个大区(如华南、华北)规划分片粒度,确保了绝大多数门店级库存操作收敛到单分片执行,从而显著减少分布式事务。
图2是业务原来基于MyCat的sharding架构,采用一主两从的配置,主机房位于北京,两个从节点位于乌兰察布机房作为异地容灾机房。业务数据根据地区划分不同的大区分片,每个地区数据访问经由MyCat下发到各大区分片执行,为了避免分布式事务,业务层面尽量保证每次获取的数据都只定位到其中某个大区。

图2 基于MyCat的sharding架构
在业务的演进过程中,业务数据和业务需求随之增多,分库分表 MyCat 架构逐渐暴露出三类主要问题。
第一类问题是数据迁移困难。 当业务需要合并或调整大区时,必须进行跨库数据搬迁。整个过程脚本复杂、回滚窗口小,风险高、周期长。
第二类问题是MyCat 功能缺陷影响业务。 MyCat 仅提供基础路由能力,对复杂 SQL(多表关联、子查询、聚合统计)和分布式事务支持有限,因财务等模块的查询较为复杂,被迫将分片表改为全局表,且需要应用适配,导致数据冗余并增加维护成本。
第三类问题是扩展性差。 横向扩容需要重新划分大区并再次触发全量数据迁移,当出现性能瓶颈时,只能依赖垂直升配硬件,无法通过水平扩展快速解决。
为替代 MyCat 并解决其固有痛点,科技中心将选型范围锁定于原生分布式数据库,并明确两项核心诉求:一是高可用,零数据丢失;二是在线弹性扩展,无需停服或搬迁数据。
经过市场调研和多轮评估,百丽科技中心最终选定 OceanBase。下文将以财务核心系统从 MyCat 升级至 OceanBase 的项目为例,系统梳理数据库替换过程中的关键实践。无论采用哪一种替换方案,均需围绕三个核心步骤展开。
- 数据流转:梳理全链路数据流,明确数据从哪里来、到哪里去。
- 数据校验:确保数据正确性,验证准确性和一致性。
- 兼容与调优:识别兼容、性能问题,并治理。
第一步:数据流转
MyCat 架构下
上游数据同步链路如图三所示。
- 主数据 MySQL:通过 MyCat 以全局表方式向各大区 DB 下发集团各业务通用数据。
- 财务应用:其他业务系统也会将数据同步到 MyCat,因为不同业务对应的分区是相同的,所以不同业务间的数据同步是通过DB一一对应的方式进行。
- 同步工具:红色链路代表数据同步链路,统一采用阿里开源工具 Otter。

图3 MyCat架构下,上游数据同步链路
下游数据同步链路如图4 所示。
- 数仓:通过 Binlog 抽取实现入仓。
- Oracle:财务系统的业务数据需同步到#Oracle 进行报表分析。
- 同步工具:红色链路代表数据同步链路,统一采用阿里开源工具 Otter。

图4 MyCat架构下,下游数据同步链路
OceanBase 架构下
如果使用 OceanBase 替换 MyCat,上线后能否打通现有数据链路正常流转呢?
上游(见图5)以 OceanBase 作为目标端的链路实现比较简单,只需修改目标端配置即可实现数据同步,可以维持旧方式进行同步。

图5 OceanBase架构下,上游数据同步链路
相对上游,下游的替换比较复杂。之前 MyCat 架构下是基于 Binlog 实现的数据同步,如果替换为 OceanBase,无法直接提供 Binlog 日志以供下游消费。 那么如何同步数据到下游呢?有两种解决方案(见图3)。
第一种方案: 在Fas OceanBase部署OceanBase Binlog Service来生成 Binlog,对整个数据链路来说,基本可以通过 Otter 跑通整个链路,兼容性是最好的,改动最小。但也存在一些问题,比如MyCat 中有八个MySQL分片,相当于8个线程去采集8个数据库实例的数据。由于 OceanBase Binlog Service 是以租户为维度,无论是生产Binlog还是消费Binlog,都只能有1个线程去处理。在业务高峰期间, 可能存在性能瓶颈。
第二种方案: OMS 将数据变更下发到 Kafka,通过这种方案,数仓能够以较低的延迟快速抽取数据,从而满足实时报表及其他高时效性业务需求,解决了方案一的性能问题。同时由于数据仓库和部分数据同步到 Oracle 需求,对实时性要求极高,也必须采用 OMS 到 Kafka 的链路实现。为此,需要开发数据同步工具,完成下游从 Kafka 到 Oracle 的数据流转需求。

图6 MyCat替换为OceanBase同步数据至下游的两种方式
关于 OMS 的使用经验,我们总结了几点实践中遇到的问题与注意事项。
其一,OMS 插入存在冲突会在日志打印,不影响复制。
OMS 在插入数据时,若检测到数据冲突,会在日志中记录相关信息,不会中断复制流程。这意味着,例如在分库场景下,即使存在组件冲突,OceanBase 通过 OMS 的链路仍将持续运行,不会因此中断。对此,我们需在后续工作中加强数据校验机制,及时发现并处理潜在的数据一致性问题。
其二,OMS V4.2.5.2 之前的版本需要关注字段超过 4K 的复制情况。
在 OMS 4.2.5.2 之前的版本中,对于超过 4K 的LOB字段行外存储的话,执行DML时OBCDC可能不吐出LOB列的前镜像,导致下游数据不一致。具体表现为:若某行数据未对该大字段进行修改,OMS 在将变更消息下发至 Kafka 时,会将该字段内容置为空。这一行为对一般依赖全镜像复制的数据同步工具而言并不友好。例如,如果仅修改更新时间,也可能导致大于 4K 的字段被置空,从而影响下游数据的完整性,建议使用4.2.5.2以后的版本(OMS 4.2.5.2版本已解决该问题)。
其三,OMS 下发数据变化到 Kafka,从消费角度 Hash 性能最优,但是要考虑是否存在唯一键的问题。
OMS 支持两种数据变更下发方式:一种是以表维度,另一种是以主键 Hash 分区维度。从消费者角度考虑,主键 Hash 分区的性能最好。但需要考虑某些场景目标端存在的唯一键问题,可能会导致数据丢失。
以我们遇到的场景为例:假设有一张表(tab1),有一个主键(id)和一个唯一键(uniq_col),我们对该表依次执行以下三步操作:
- 插入一行数据:insert into tab1 values(1,'a');
- 按照唯一键删除数据:delete tab1 where unique_col = 'a';
- 插入一行 ID 为 2 的数据:insert into tab1 values(2,'a');
如图7所示,当上述变更通过 OMS 下发至 Kafka 时,若采用 ID 作为哈希值,(1,'a') 和 (2,'a') 很可能不被分发到同一个 Partition 中。在 Partition1 中,同时存在 insert 和 delete,而在 Partition2 中,只有一条 insert 记录。

图7 OMS 下发数据变化到 Kafka时可能存在的结果
由于下游消费者在消费消息时存在各种情况,可能不按照语句执行顺序进行,无论下游的数据同步采取 insert into 模式还是 insert into ... on duplicate update... 模式,都有可能遇到 (2,'a') 数据丢失的情况。
如果下游的数据同步采用insert into 模式,在按照图8的顺序消费时,先插入 (1,'a'),再继续消费 msg3 插入 (2,'a') ,此时由于 a 列冲突不再执行,最后消费 msg2,导致 (2,'a') 数据丢失。

图8 下游的数据同步采用insert into 模式
如果下游的数据同步采用 insert into ... on duplicate update... 模式(见图9),先插入 msg3 即 (2,'a') ,后续基于 insert into ... on duplicate update 模式,在消费 msg1 时,一旦 a 列出现冲突,会将 a 列的值更新为1,最后消费 msg2,导致 (2,'a') 数据丢失。

图9 下游的数据同步采用insert into ... on duplicate update...模式
上述 OMS 以主键 Hash 分区模式下发 Kafka 在消费时可能存在的问题,本质是因为在主键 Hash 分区模式下,不同 Partition 存在并发修改同一行时同时叠加了唯一键导致的。因此在上述 OceanBase 架构下 OMS 将数据变更下发到 Kafka 的第二个方案中,消息按表还是主键 hash 分区取决于两点:一是对高性能有无需求,二是如果下游的表没有唯一键,也可以按照主键 Hash 分区方式进行。
反向同步
图10是业务切换前后的数据链路,不同颜色的链路代表不同的数据传输工具:红色链路代表 Otter、蓝色链路代表 OMS、绿色链路代表百丽自研的数据同步工具 SQLapplier、黑色链路代表其他工具。

图10 业务切换前后的数据链路
切换前,业务数据通过 OMS 同步到 OceanBase,OceanBase 通过 OMS 下发到 Kafka。同时在上线前需要做数据同步测试,通过 Kafka 将数据同步到测试 Oracle 和测试 MyCat,持续验证同步工具的性能和功能适配。
数仓可以提前验证和切换。业务切换时,需要暂停应用和上游业务的同步,此时 MyCat 和 OceanBase 处于相对静止的状态。然后需要停止 OMS,将 Kafka 反向同步到 MyCat 和 Oracle,再将上游业务指向 OceanBase 即完成了切换过程。反向同步的意义在于,如果在切换初期出现任何问题可以及时回切,提高系统容灾能力。
第二步:数据校验
数据流转完成后一般需要进行数据校验,对于单库迁移,可以直接使用 OMS 完成数据校验,在重复多次校验时,可根据数据不一致情况生成订正数据。如果源端是 MyCat 的情况,可以搭建源端为 MyCat,目标端是 OceanBase 的校验,但由于百丽使用了很多 Otter 工具,同时有一些 MySQL、Oracle的异构数据库校验需求,因此使用了内部自研的工具(见图11)。

图11 使用自研工具进行数据校验
数据校验基本原理
以图12为例,如何校验对应行数据在目标端是一致的,即把各个字段拼成一个字符串,然后做 crc32 校验。如果两端的 crc32 匹配,则源端和目标端的数据一致。如果对某一端的数据做简单修改(如加一个空格),那么数据将会有很大的变化。对于整表来说,将按照一定的行数拆成多个 chunk,以 chunk 的维度进行目标端和源端的 crc32 比对。如果出现数据不一致的情况,将进行重试,经过多次重试后数据还是不一致时,会进行分裂;如果多次分裂数据还是不一致,将最终转换为上文行数据的暗行(字符串)来进行校验。

图12 例证校验对应行数据在目标端是一致的方法
数据校验问题汇总
图13是将平台中 OceanBase 作为源端,Oracle 作为目标端的数据校验过程,在我们测试过程中一共发现了4个问题。
- 业务数据异常。由于 MyCat 约束较小,随着长时间使用,以及有变更迁移数据等操作,可能会遗留一些历史问题,例如 ID重复。
- 唯一键约束范围差异导致数据丢数。MyCat 的唯一约束只能约束到 DB 分区维度中的约束,但在 OceanBase 中是全局约束,这种差异也会导致数据丢失。
- Kafka 消费 Hash 分区、下游唯一键约束丢数。
- OBServer V4.2.5.2 之前 4K 大字段丢数。

图13 将平台中 OceanBase 作为源端,Oracle 作为目标端的数据校验过程
数据校验覆盖了数据治理和数据正确性、数据一致性校验,在上线前解决存在的数据异常问题,是一项非常重要的工作。
第三步:SQL 兼容及性能测试
在打通数据链路、完成数据校验后,需要解决的就是 SQL 兼容性和性能问题,例如如何对比 MyCat 和 OceanBase 的数据库性能差异,OceanBase 性能是否能满足我们的业务需求等。针对上述需求,一个朴素的方法是:可以将 MyCat 中所有SQL 在 OceanBase 中实现,即可完整地测试兼容性问题以及性能表现。
为此我们开发了流量回放功能,如图14所示,通过数据库管理平台在各个 DB 中采集全量日志,然后解析为 CSV 格式,最终将所有 CSV 文件整合即可形成解析报告,用于分析集群层面的整体 SQL 分布、DDL、DML 等情况。将 CSV 回放到 MyCat、OceanBase 后,形成回放对比报告。

图14 流量回放的执行过程
看到该过程的你可能会有两个疑问:
- 为什么用全量日志?全量日志的好处在于全局变量便于开关,如果发现性能有压力,可以选择关掉。
- 为什么用 CSV 格式?这是因为考虑到兼容性问题。例如目前 OceanBase 能够将 SQL 转成 CSV 格式,后续可以直接从 OceanBase 的 SQL Audit 中捞取 SQL,并以 CSV 的格式保存,同样可以跑通回放流程。
回放报告
回放报告中的统计信息(见图15)包括:将所有回放 SQL 进行参数化形成模板生成对应的 SQL ID;该 SQL 使用到的表;每个 SQL ID 的最小响应时间、最大响应时间、平均响应时间、执行次数、错误次数、对应 SQL 等。

图15 回放报告中的统计信息
通过回放报告,我们可以进行兼容性分析,确定优化范围和任务分配,并持续进行回放,从而提升工作效率。
兼容性分析。通过比较源端和目标端的执行结果,检查是否存在兼容性错误。比如报告中显示存在错误,需要进一步核实错误原因是超时还是 SQL 语句本身不兼容,从而准确定位 SQL 语句的兼容性问题。
确定优化范围。回放报告可以帮助我们确定需要优化的 SQL 语句范围。由于报告生成了大量 SQL 语句,并非所有 SQL 语句都需要优化。报告中提供了每个 SQL 语句的平均响应时间、执行次数等数据,通过这些数据可以评估 SQL 语句性能,从而明确优化范围。
任务分配。在确定了优化范围后,如何合理分配任务成为一个关键问题。最初,任务分配可以比较随意,直接根据 SQL ID 进行分配,但在每周的慢查询研讨会中,我们逐渐发现这种分配方式可能导致工作效率低下。为了改善这种情况,我们利用之前收集的表组信息 tablelist ,以表组为维度进行任务分配,这不仅提高了慢查询治理的效率,也避免了重复工作。
持续进行的回放。由于回放报告会多次回放,尤其是在流量变化较大的系统中,如财务系统在月初和月末的流量可能差异很大。因此,我们会从月初到月末持续抓取流量,并进行多次回放。然而随着报告数量的增加,横向比较越来越不方便。为了解决这个问题,我们将报告整合到平台中,并以 SQL ID 作为关键要素,将每次回放的报告串联起来,以便于分析和比较。
SQL 持续治理及跟进
图16是我们平台的 SQL 持续治理及跟进面板的截图,可以展示每条 SQL 在每一轮回放中的变化,每个 DBA 只需要关注自己负责的 SQL 即可。例如图中所示的 SQL,我们在根据表组进行调优后,可以看到它的最大响应时间等数据明显下降,证明回放报告对于 SQL 诊断和治理带来的效率提升是非常直观的。

图16 平台的 SQL 持续治理及跟进面板
此外,值得一提的是OCP 有一个非常实用的功能,可以根据特定时间点恢复数据。在进行压力测试及流量回放过程中,可能会涉及对数据执行 DML 操作,从而对数据造成修改。面对这种情况,OCP能够迅速将数据恢复至某一时间点的数据副本,便于我们立即将数据投入使用。使用完毕后,可以将其删除。对此,我们认为这一功能极具价值。
SQL 问题分类
在进行 SQL 治理和调优过程中,我们共发现了四个问题。
问题1:部分SQL不兼容。
在 SQL 使用过程中,我们通常用“--”进行注释,放在 SQL 语句最后。在 MySQL 中一般不会发生报错,但在 OceanBase 中报错了,研发团队直接进行了修改。值得肯定的是,在回放了大约4.5万个 SQL ID 后,发现的不兼容问题仅有这一个,由此看出OceanBase 对 MySQL 5.7 版本的语法兼容度是非常高的,基本无需在兼容性方面投入过多的工作量。

图17 不兼容的SQL
问题2:RPC 代价高。
当使用多组模式进行查询时,如果 SQL 涉及多个 OBServer,可能会导致网络开销增大,特别是在处理大量数据的情况下,可能会显著降低查询效率。解决该问题需要进行分片表表组设计或者对于相对稳定的主数据表,设计复制表。此外,为了快速判断是否为 RPC 问题,可以通过恢复一个单主环境,并在该环境中执行 SQL,然后与多主环境进行性能对比,从而有效判断问题是否由 RPC 代价引起。
问题3:分区裁剪。
分区裁剪是另一类需要花费大量时间进行调优的问题。例如,在涉及 DTL 订单明细表的 order by 关联查询中,指定某个大区条件,在 MyCat 中没有图18所示红框中的条件,这是因为 MyCat 的分区规则相同,即在物理层面进行了隔绝,本来就在一个大区内,所以不需要对大区进行指定。而在 OceanBase 中,如果将这个条件去掉,会引发 om 表正常进行分区裁剪,但 od 表不知道需要在这个大区内进行,因此 OceanBase 需要指定这个条件以确保分区裁剪的正确性。这是一个非常典型的分区裁剪问题,其根本原因在于 MySQL 的机制在某些方面并不完善,原本物理隔绝的 SQL 在 OceanBase 是一个完整的库,这就需要我们在 OceanBase 中进行相应的调整和优化。

图18 补充分区条件
问题4:执行计划问题。
执行计划问题涉及几个关键参数。
- partition_index_dive_limit 参数是 SQL 采样分区参数,可能会影响执行计划的评估,如果采样分区较小且数据为空,可能会导致采样误判,影响代价评估,建议根据实际需求将参数调大。
- 大小参数的问题,指同一 SQL 在不同变量下读取的数据差异较大,但使用了相同的执行计划,可能会导致性能问题,此时可以使用 /+USE_PLAN_CACHE(NONE)/ 进行规避,但这会使得每次执行该SQL都硬解析,有额外的CPU开销,需要综合评估使用。
- 如果 in 参数过多,可能会导致硬解析时间过长,此时可以适当调整参数_inlist_rewrite_threshold,使 in 参数到达一定阈值后可以进行改写以避免硬解析的代价。
问题汇总
在实际应用中,我们还遇到了一些其他问题:
- l- ocal rescan 计划不优,低代价的 nlj 计划由于 local rescan 的规则被错误裁剪,导致 SQL 最后走了高代价执行慢的 hash join,该问题出现在 OceanBase V4.2.5.3 之前的版本,已经在 OceanBase V4.2.5.3 版本修复。
- 调整 tablegroup,手动发起均衡,若存在空分区,均衡计算可能会导致任务卡住,该问题出现在 OceanBase V4.2.5.3 版本,已经在 OceanBase V4.2.5.4 版本修复。
- 包含复制表的 SQL,一定情况下会存在无法复用执行计划的情况,该问题出现在 OceanBase V4.2.5.4 版本,已经在 OceanBase V4.2.5.5 版本修复。
切换收尾:平台适配
我们内部使用 Archery 工单平台完成 SQL 的管理和发布,并且现有的 MySQL 等数据库也都在使用 Archery 工单平台,因此我们计划使用该平台接入 OceanBase。
目前,OceanBase 已经对接了 goInception 项目(https://github.com/whhe/goInception),可以实现 OceanBase 资源类型的工单回滚,即结合 OBServer 完成 SQL 的回滚操作。
在使用 Archery 平台管理 MySQL 时,我们通常通过 ptosc或 gos 等方式实现 Online DDL 操作。然而,这种方式对于 OceanBase 的离线操作,可能会直接锁表。
针对这种情况,我们期望达到的效果是:提交工单时,无论是 DBA 还是研发人员都能够识别出操作是 Online 还是Offline。过去我们依赖于肉眼判断,为了改进这一流程,我们增加了一项小功能:在提交工单时,我们会在测试环境中的 OceanBase 中运行一遍,检查 Table ID 是否发生变化。如果 Table ID 发生变化,则表明操作是 Offline 的;如果没有变化,则表明操作是 Online 的,告警信息如图19所示。

图19 告警信息
这一设计虽然简单,但效果显著,研发人员在提交工单时可以一目了然地知道操作是在线还是离线,大大提高了工作效率。
百丽核心系统为什么选择OceanBase?
以上就是百丽财务系统从MyCat迁移至OceanBase的技术经验总结,在此过程中,非常感谢 OceanBase 社区团队在我们项目测试及切换过程中的密切关注与大力支持。 那么,为什么我们会选择OceanBase,而不是同样作为开源分布式数据库的TiDB、PolarDB……呢?
理由可以归纳为三个方面。
第一方面是OceanBase的技术优势:
- 可靠。Paxos 多副本机制,RPO=0,故障自动切换,数据零丢失。
- 弹性。单机型与分布式模式可在线互转;多租户隔离;高压缩比降低存储成本;容量可按需横向扩展,无需提前重度预估。
- 统一。原生 HTAP,同一套引擎同时支撑 TP、AP、KV 及向量检索,后续引入新负载无需新增技术栈。
- 易用。提供 OCP、OMS、ODC、OBAgent 等完整工具链,显著降低部署、迁移、监控、运维门槛。
第二方面是社区活跃,OceanBase保持完全开源与快速迭代的风格,对于用户的问题及时响应,确保了用户的技术交流渠道畅通。同时,社区经常开展技术交流活动与培训课程,不断加强用户对于问题的解决能力。此外,用户对于其版本发布节奏也是可预期的。
第三方面是行业验证,OceanBase在金融、运营商、零售等高要求行业规模化上线,历经核心系统长时间运行考验,稳定性已经得到大量企业的充分证明。
浙公网安备 33010602011771号