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