*本文转载自微信公众号 “携程技术(ID:ctriptech)”,作者提挈、Cong、Typhoon。
提挈:携程资深数据库工程师,专注于数据库自动化运维和分布式数据库的研究。
Cong:携程数据库专家,主要负责MySQL和分布式数据库运维及研究。
Typhoon:携程高级数据库工程师,负责分布式数据库的运维和工具设计。
MySQL 在业界流行多年,在很长一段时间很好地支撑了携程的业务发展。但随着技术多元化及业务的不断发展,MySQL 也遇到了新的挑战,主要体现在:业务数据模型呈现多元化,OLTP 和 OLAP 出现融合的趋势;在 MySQL 数据库上慢查询治理成本高;使用传统的分库分表方案对开发不友好,核心数据库改造成分库分表方案,时间一般以年为单位。
分布式数据库能比较好地解决上述问题,同时也带来了新的挑战。2021年,OceanBase 开源,携程开始逐步探索 OceanBase 的基本特性和应用场景。
OceanBase 兼容大部分 MySQL 的功能和语法,同时提供水平扩展性、强一致性和高可用性,能满足业务需求并降低运维成本。因此,我们开始推进部分 MySQL 实例迁移到 OceanBase。为保证迁移顺畅,我们设计了迁移评估工具、OceanBase 迁移流程、OceanBase 监控大盘和 OceanBase 故障诊断工具等,并将迁移过程中遇到的问题和大家进行分享。
评估工具
平滑迁移异构数据库,我们需要进行兼容性、性能和分区适应性等各项检查。提前把不兼容或有可能引起迁移异常的场景找出来并解决。官方提供了OceanBase Migration Assessment(OMA)工具,用于异构数据库迁移到 OceanBase 的可行性评估。迁移评估工具 OMA 有语法兼容性检查和性能评估,但还不能完全满足我们的需求。主要体现在下面几点:
- 中间件版本检查, 一个 DB 有多个应用在访问,只有某个版本后的中间件才开始支持 OceanBase,需要检查访问该 DB 的所有应用的中间件版本,并督促开发进行升级,以确保都在支持 OceanBase 版本之上。
- 性能采集和回放提供的 MySQL General Log 采集模式有一定风险, 尤其是对于业务繁重的数据库,我们需要更平滑的性能采集和回放方案。另外对于单实例多 DB 场景,存在迁移和不迁移的 DB 共存的情况,需要进行过滤。
- 线上存在非通过中间件访问的数据库账号, 如 ETL 取数账号、数据查询工具账号、应用直连账号等,对其兼容性需要进行检查。因为迁移到 OceanBase 之后,数据库登录账号需要进行改变,包含租户信息。
- OceanBase 是分布式数据库,数据如何进行分区就显得非常重要, 以避免形成热点数据。一张表可能有多个字段都适合作为分区键,在迁移工具中,根据数据分布以及访问情况,需要提供表分区推荐,以减少迁移成本。
因此我们对 OMA 评估工具进行了拓展和改造。在不影响现有的数据库运行下,省去中间环节,做到一键评估。其中 MySQL 数据采集与分析大致流程示意图如下,全量数据导入 OceanBase 后,目标端我们用开源 Locust 工具,进行 SQL 回放和压测,并最终形成评估报告。
迁移流程
在评估流程完成并且评估结果符合迁移要求的前提下,可以发起 MySQL 到 OceanBase 自动迁移流程。为减少迁移成本,我们把迁移流程进行了封装,做到一键自动迁移,自动切换包含以下流程:
- 1)迁移前配置校验。 迁移前,会集中对所有的切换注意事项和相关配置再进行一次全面的检查,提前排除配置问题可能导致的切换风险。
- 2)MySQL 账号兼容 OceanBase 带租户账号创建。 由于 OceanBase 是多租户管理模式,应用的连接串必须指定租户名,因此相应账号需要在目标 OceanBase 集群预先创建,中间件或工具切换账号时,只需重置连接并切换到新账号即可。
- 3)数据一致性校验。 数据通过 Canal 从 MySQL 同步到 OceanBase 后,我们需要对一致性做校验。校验的方法是根据表主键进行切分,进行结果集比较是否一致。当遇到热点表时,数据校验过程会发起多次尝试来反复验证。
- 4)DDL 表结构修改暂停。 由于 MySQL 和 OceanBase 表结构变更方式差异较大,当 DB 迁移从 MySQL 到 OceanBase 触发流程后,我们会在源 MySQL 禁止 DDL 操作。当然,如果开发有紧急发布需求,我们可以废弃流程,等 DDL 发布完成后,再重启迁移流程。
- 5)反向同步链路搭建。 无论前面的迁移评估或者流程多么完善,反向同步链路对于异构数据库的迁移是必备的。一旦迁移出现异常,可以快速回退。反向同步链路是基于 OceanBase 的 CDC 服务,订阅增量日志在 MySQL 端回放,保证迁移后 OceanBase 侧和 MySQL 侧数据始终一致。
当数据同步完成,并且没有增量延迟后,迁移流程将生成具体的切换任务,切换流程如下:
我们只需要在预定的时间窗口内,点击触发切换流程,就可以完成从 MySQL 到 OceanBase 的切换。整个切换流程可在一分钟之内完成,而且业务端无需进行改造。我们拥有反向链路,如碰到有异常情况,可以随时安排回退。反向链路在正常情况下将保留两周以上。
OceanBase监控
分布式数据库和单机数据库一个比较大的区别在于分布式监控比单机版数据库更为复杂。一是因为组件众多,需要有一个全局视点;二是因为需要对告警点进行聚合。业务新迁移到 OceanBase 时,观察集群监控、关注告警信息是判断迁移成功与否的关键。日常的冒烟现象或者不规范现象,需要及时发现、及时处理,避免问题恶化。准确监控和及时告警可以帮助运维人员快速定位问题,快速解决故障。
▋ 监控大盘
OceanBase 的监控数据主要通过在每台 Server 上部署的 Agent 程序从本地直接采集。Agent 中包含众多组件,内容如下:
Agent 程序会向 hickwall 上报采集到的数据,以模板化的形式展示出来,以此形成监控大盘。如下图所示:
▋ 告警邮件
OceanBase 的告警,主要通过订阅 hickwall 上的监控数据以及定时的服务巡检来完成。基于采集的监控数据设立告警阈值,一旦指标超过阈值便会进行告警通知。另外,我们还会对配置进行定期检查,来解决规范性问题等。
▋ OceanBase SQL审计
OceanBase 接入了携程的 SQL 审计流程。与以往传统的审计插件模式不同,现在以抓取网络包的方式,通过对 MySQL 协议解析得到全量的 SQL 审计信息。接入审计流程后,可以快速定位到 SQL 信息,包括应用编号、访问 IP、执行参数、有无报错信息等。
▋ OceanBase 审计运用案例
在使用 MySQL command-line tool 连接OceanBase过程中出现连接不上的错误时,我们使用 SQL 审计日志进行定位,发现客户端在连接 OceanBase 的过程中会执行一些元数据查询工作,在进行 show tables 这一步骤后会报错断连,后续定位到一个特殊的表,该表表名的最后一个字符是分号(t_sample;)导致了这次报错,随即我们在开源社区反馈了这例问题。
OceanBase自动故障诊断
随着越来越多的 MySQL 迁移到 OceanBase,数据库性能、故障定位的实时性和准确性的要求变得越来越高。自动故障诊断系统可以全方位、及时、精准地定位线上问题,为运维和排障提供依据。
▋ 构建实时性能数仓
OceanBase 性能数仓构建的流程图如下:
收集性能指标相关数据,以下是常用的性能指标对应的数据源:
开发数据收集程序,在服务器本地每 10 秒采集一次上述性能指标的数据。并在采集之后对数据进行结构化处理,包括对数值型数据进行标准化处理,对文本型数据进行时序化处理。
将结构化处理之后的数据落地存储到 ClickHouse 中。
▋ 自动化分析
自动化分析的流程图如下:
▋ 实时检测性能指标
通常判断性能异常的指标包括 CPU 占用率、磁盘 IO 占用率、Threads Running、QPS、网卡流量等。基于运维经验,可以针对每个指标设定相应的阈值,当突破阈值时,则认为当前实例存在性能问题。比如 CPU 占用率高于 65% 或磁盘 IO 占用率高于 80% 则代表服务器出现异常。
▋ 异常数据匹配数仓
首先,对于数值型数据,分析工具会自动选取故障指标和故障时间段,通过相似性匹配数仓中数据所有数值型数据包含 SQL、Table、Perf 三种类型,它们相关的性能指标说明如下:
- SQL对应的性能指标: 执行次数、总耗时、CPU 耗时、逻辑读次数、物理读次数等。
- Table 对应的性能指标: 增删改行数、增删改的 SQL 数、相关事务数等。
- Perf 对应的性能指标: CPU、I/O、RPC 时长、索引缓存大小、缓存命中率等。
- 其次,对于文本型数据,分析工具会通过故障时间区间获取所有时序化的文本数据,通常包含:
- 数据库服务日志、系统内部任务记录、数据库进程信息等。
- 最后,基于前面两种类型的数据进行综合性分析,分析要点主要有:
- SQL 层面: SQL 性能消耗占比、有无正在执行的慢 SQL、是否缺失索引、是否存在远程执行或分布式执行等。
- OceanBase 内部: OceanBase 是否在做合并、是否正在均衡副本、是否存在其他异常日志等。
- 应用层面: 客户端是否进行发布。
最终基于以上自动化分析,实现服务器性能波动真实原因的精准定位,自动生成故障定位分析报告, 并通过邮件及时推送给 DBA 和相关开发人员。
▋ 运用案例
下面基于该工具自动生成的一例分析报告来介绍该工具的实际运用:
报告的故障指标板块显示 4:30 后服务器的 CPU 上升;
报告的 OceanBase 相关表板块显示 CPU 上升趋势和下面这张表的访问趋势一致;
报告的 OceanBase 相关 SQL 板块显示这张表的访问趋势和下面的 SQL 语句访问趋势一致;
报告的分析结果板块定位到 CPU 上升和 tablex 表的访问上升有关,而这张表的访问上升又和这 1 条 SQL 语句访问耗时增长有关,最终定位由于该 SQL 导致 CPU 上升。后续我们联系开发确认是正常业务上升,并添加服务器节点缓解 CPU 负载。
迁移遇到的问题和实践
▋ .Net 应用访问 OceanBase 失败
在使用和测试 OceanBase 的过程中,我们发现 .Net 应用的官方 MySQL 连接器连接 OceanBase 执行 SQL 失败。
经排查,我们发现.Net应用依赖连接中的ConnectionCharSetIndex,而OceanBase不存在ConnectionCharSetIndex=83即utf8_bin,只有utf8mb4_bin。因此我们对OceanBase的源码进行了修复来满足这类应用对 OceaBase 的适配性。
总结:OceanBase不够完美,但是随着时间推移,通过反复的测试和迭代,正在逐步完善它的各方面。我们也参与其中,以运维和产品使用者的视角对它进行优化和完善。
▋ Druid 应用不兼容部分 OceanBase 语法解析
我们在开发 OceanBase 表结构设计工具的时候,发现 OceanBase 的 SQL 通过 Druid 解析时存在报错。这个错误会导致在表结构设计的时候导入 SQL DDL 语句报错。遇到问题后,我们先调整到 Druid 最新版本,发现问题仍然存在。
我们将问题先从复杂的表结构设计中抽离出最简单的 SQL DDL, 并结合分析 Druid 的源代码,发现原来 Druid 代码对 OceanBase 的兼容在 SQLIndexDefinition 中实现,但没有在 SQLIndexOptions 实现。根据 OceanBase 的语法树,实际应该在 SQLIndexOptions 实现才合理,找到问题所在后,我们提交了 Pull Request, 然后被合并到 Druild 主线。问题得以解决。
总结:开源工具的一个好处在于碰到问题后我们可以进行代码分析。并快速定位问题,最后反馈社区。
▋ OceanBase读写分离支持
读写分离是数据库非常重要的能力,在业务层面上,它覆盖到了 ETL 取数,BI 报表生成,缓存刷新等多个场景。OceanBase 虽然支持读写分离功能,但需要在代码层显性设置弱一致性读参数,存在对业务高度侵入的缺陷。我们对 OceanBase访问代理OBProxy做了代码改造,新增enable_weak_read以及weak_read_user_list 两个参数,通过代理层控制开启读写分离策略,对应用透明度高。
读写分离场景下,应用与 OBProxy 建联的流程示意图如下:
基于以上的代码修改,我们设计了一套优化版本的读写分离方案,即通过以账号维度来控制是否使用读写分离。流量调度示意图如下:
总结:OceanBase 源生虽然提供了强大的功能,但是它并不一定 100% 满足业务的场景和需求,因此对其组件进行二次开发是有必要的。我们不单单对于 OBProxy 进行了相关的功能适配,对于其他组件如 cdc、Deploy 组件等我们也根据实际场景需求,进行相应调整。
▋ query range过大导致内存溢出
在初期使用 OceanBase 时,我们有碰到过 Server Crash 的经历。当一个查询的条件中 IN 运算符中包含过多元素(一万级别以上)时,会爆出 stack overflow 的异常。
经过分析和社区交流,我们定位到优化器在抽取 query range 会耗费大量的内存。而 OceanBase 在算法迭代过程中没有检查查询超时,导致该查询一直消耗内存,直到用尽了 SQL ARENA 的内存。这种模式没有做好防御机制,从而导致内存溢出造成系统崩溃。这个问题在新版本中已经得到修复。当确认到问题后,我们第一时间通知开发减少 IN 内的元素数量,并安排了版本升级。
总结:OceanBase 作为新鲜产品,社区论坛和 Git issue 是获取日常运维和快速排障方案的利器,根据各种技术探索和交流分享,可以汲取优质内容,收获前沿知识,快速定位和解决问题。
▋ 修正执行计划
在迁移前后,数据库的 SQL 性能是最值得关注的地方。作为分布式数据库,OceanBase 的优化器相较于 MySQL 来说更复杂并且由于其特殊的存储结构导致表的统计直方图刷新频率很低,因此当可用索引和查询条件的适配度不高时,优化器在选择执行计划时可能存在偏差。OceanBase 自带修正执行计划的能力,即通过在数据库层面直接指定同类型 SQL 以 outline 注释的方法强制绑定执行计划。
总结:OceanBase 相较于传统数据库,其分布式的架构和特殊的存储结构也会带来运维门槛的提高,不过它同时也给予运维人员更高的自由度。运维人员需要熟悉并掌握这些强大的功能和运维技巧,使线上业务具备更好的稳定性。
未来展望
OceanBase 开源已经一年有余,我们的运维工具也逐渐趋于成熟,运维能力也在逐步提高。越来越多的 MySQL 正在逐步往 OceanBase 上迁移。随着 OceanBase 4.0 版本的推出,许多新特性也已经在逐步测试中。我们对 4.0 版本的新功能也非常期待。
▋ 单机分布式一体化架构
OceanBase 4.0 版本推出单机分布式一体化架构,支持类似 MySQL 的轻量化单机模式部署,同时也可以在必要时迅速地扩容成分布式模式来提高性能上限。单机与分布式的灵活切换可以大大降低成本,并且基于源生主备库的能力可以快速的完成主备的 DR 切换,有更强的高可用性保证。
▋ 兼容性增强
OceanBase 对 MySQL 的高兼容性一直是我们考量的重点,高度兼容为开发同事节省了大量学习成本和代码成本。在 4.0 版本中,在字符集、约束、函数、存储过程等多方面与 MySQL 的匹配度更高,在使用上与 MySQL 更加接近。
当然,兼容性还包括对 MySQL 生态的兼容,包括 binlog 兼容、canal 兼容、闪回工具兼容等等。
▋ 运维能力提升
OceanBase 作为分布式数据库,组件多、运维环境复杂是痛点。我们后续将基于现有的日志收集工具和分析工具,完成链路式的问题诊断,更精准地定位性能问题、集群内部任务问题等。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。