近日,Facebook 官博颁布了他们的数据库版本从 MySQL 5.6 降级到了 MySQL 8.0,并且在官博记录了复盘具体的降级过程。
Facebook 称,他们最近的一次大版本升级到 MySQL 5.6 花了一年多工夫才实现,还在 5.6 版上开发 LSM 树存储引擎,MyRocks。在降级到 5.7 的同时构建一个新的存储引擎,会大大减慢 MyRocks 的进度,因而咱们抉择持续应用 5.6,直到 MyRocks 实现,MySQL 5.6 的寿命也行将完结,决定降级到 MySQL 8.0。
官博介绍说,此次过程比之前的降级更具挑战。
MySQL 是由 Oracle 公司开发的一个开源数据库,它为 Facebook 的一些最重要的工作负载提供了能源。咱们踊跃开发 MySQL 中的新个性,以反对一直演变的需要。这些个性对 MySQL 的许多方面进行了批改,包含客户机连接器、存储引擎、优化器以及复制。为了迁徙工作负载,对于每个新的 MySQL 主版本,咱们都须要投入大量的工夫和精力。其中的挑战包含:
- 将自定义性能移植到新版本
- 确保次要版本之间的复制兼容
- 最小化现有应用程序查问所需的更改
- 对妨碍服务器反对咱们工作负载的性能进化进行修复。
咱们最近一次的主版本升级是到 MySQL 5.6,它花了一年多的工夫才推出。当 5.7 版公布时,咱们还在 5.6 版上开发 LSM 树存储引擎和 MyRocks。在降级到 5.7 的同时构建一个新的存储引擎,会大大减慢 MyRocks 的进度,因而咱们抉择持续应用 5.6,直到 MyRocks 实现。MySQL 8.0 公布之际,咱们正在做 MyRocks 向用户数据库(UDB)服务层推出的收尾。
该版本包含一些引人注目的个性,如基于写集的并行复制和提供原子 DDL 反对的事务数据字典等。对咱们来说,迁徙到 8.0 还将带来包含文档存储在内的,咱们曾经错过的 5.7 个性。版本 5.6 的使命行将完结,咱们心愿在 MySQL 社区中放弃沉闷,尤其是在 MyRocks 存储引擎上的工作。
8.0 中的加强性能,比方即时 DDL,能够放慢 MyRocks 的模式更改,然而咱们须要在 8.0 的代码库中应用它。思考到更新代码的益处,咱们决定迁徙到 8.0。上面将分享咱们如何解决 8.0 迁徙我的项目的难题,以及在这个过程中发现的一些惊喜。当最后确定我的项目范畴时,能够明确的是,迁徙到 8.0 会比迁徙到 5.6 或 MyRocks 更艰难。
- 过后,咱们定制的 5.6 分支有 1700 多个代码补丁须要移植到 8.0。在咱们移植这些更改时,新的 Facebook 的 MySQL 个性和修复已被增加到 5.6 的代码库中,从而使指标变得更加遥不可及。
- 咱们有许多 MySQL 服务器在生产环境中运行,为大量截然不同的应用程序提供服务。咱们还有泛滥治理 MySQL 实例的软件架构。这些利用执行诸如收集统计数据或治理服务器备份之类的操作。
- 从 5.6 降级到 8.0 齐全跳过了 5.7。在 5.6 中处于活动状态的 API 在 5.7 中可能被弃用,而在 8.0 中可能会被移除,这要求咱们必须更新所有应用了现已删除 API 的应用程序。
- 许多 Facebook 性能与 8.0 中的相似性能并不向前兼容,须要一种弃用或迁徙路径。
- MyRocks 的加强性能须要在 8.0 中运行,包含本地化分区和解体复原。
1、代码补丁
首先咱们建设了 8.0 分支,用于在开发环境中进行构建和测试。而后,咱们开始从 5.6 分支移植补丁的漫长过程。开始的时候有 1700 多个补丁,但咱们能将其组织成几个次要类别。
咱们的大多数自定义代码都有很好的正文和形容,因而能够很容易地确定应用程序是否依然须要它,或者是否能够将它删除。通过非凡关键字或惟一变量名所启用的性能,也使得确定关联变得很容易,因为咱们能够搜寻利用程序代码库来找到它们的用例。有些补丁十分艰涩难懂,须要做考察工作 — 开掘旧的设计文档、邮件或代码评审正文,以理解它们的历史。
咱们将每个补丁分入四类之一:
- Drop:不再应用,或在 8.0 中具备等同性能的个性,不须要移植。
- Build/Client:反对咱们构建环境的非服务器个性,批改过的 MySQL 工具,比方 mysqlbinlog,或者减少的性能,如异步客户端 API 等,须要移植。
- 非 MyRocks 服务器:mysqld 服务器中与 MyRocks 存储引擎无关的个性,须要移植。
- MyRocks 服务器:反对 MyRocks 存储引擎的个性,须要移植。
咱们应用电子表格跟踪每个补丁的状态和相干历史信息,并且在删除补丁时记录理由。更新雷同个性的多个补丁被组在一起进行移植。移植并提交到 8.0 分支的补丁,用 5.6 提交信息进行了正文。因为咱们须要筛选大量的补丁,将不可避免地呈现移植状态上的差别,这些正文帮忙咱们解决了此类问题。
客户端和服务器类别中的每个补丁都自然而然地成为一个软件公布里程碑。随着所有与客户端相干的更改的移植,咱们可能将客户端工具和连接器代码更新到 8.0。一旦所有非 MyRocks 服务器个性都被移植,咱们就能够为 InnoDB 服务器部署 8.0 mysqld 了。实现 MyRocks 服务器个性移植使咱们可能更新 MyRocks 装置。
有些简单个性须要对 8.0 进行重大更改,一些方面存在很大的兼容性问题。例如,上游 8.0 binlog 事件格局与咱们一些对 5.6 的定制批改不兼容。Facebook 5.6 个性应用的错误代码与上游 8.0 调配给新个性的错误代码抵触。咱们最终须要修补 5.6 服务器,以使其与 8.0 向前兼容。
实现所有这些个性的移植花了几年工夫。到最终完结时,咱们曾经评估了 2300 多个补丁,并将其中 1500 个移植到了 8.0 版本。
2、迁徙路径
咱们将多个 mysqld 实例组合到一个 MySQL 正本集中。正本集中的每个实例都蕴含雷同的数据,但在天文上散布到不同的数据中心,以提供数据可用性和故障切换反对。每个正本集都有一个主实例。其余的实例都是从实例。主实例解决所有写流量,并将数据异步复制到所有从实例。
由 5.6 主 /5.6 从所组成的正本集开始,最终目标是蕴含 8.0 主 / 8.0 从的正本集。咱们遵循一个相似于 UDB MyRocks migration plan 的迁徙布局。
- 对于每个正本集,通过一个应用 mysqldump 生成的逻辑备份,创立并增加到 8.0 的从实例。这些从实例不提供任何应用程序读取流量;
- 在 8.0 从实例上开启读取流量;
- 容许将 8.0 从实例降级为主实例;
- 禁用 5.6 实例的读取流量;
- 移除所有 5.6 实例。
每个正本集能够独立地通过上述步骤进行迁徙,并可依据须要停留在一个步骤上。咱们将正本集分成更小的组,在组中进行每一次迁徙。如果发现问题,咱们能够回滚到上一步。在某些状况下,正本集可能在其它正本集开始之前达到最初一步。
为了自动化迁徙大量正本集,咱们须要构建新的软件架构。能够通过简略地更改配置文件中的一行,将正本集组合并在每个阶段中挪动它们。任何遇到问题的正本集都能独自回滚。
3、基于行的复制
作为 8.0 迁徙工作的一部分,咱们决定将应用基于行的复制(row-based replication,RBR)作为规范。一些 8.0 个性须要 RBR,并且它简化了 MyRocks 的移植工作。咱们的大多数 MySQL 正本集曾经在应用 RBR,而那些依然运行基于语句的复制(statement-based replication,SBR)的正本集不容易迁徙。这些正本集通常有不含任何高基数键的表。齐全转向 RBR 是一个指标,但增加主键所需的长尾工作的优先级往往低于其它我的项目。
因而,咱们将 RBR 作为 8.0 的要求。在评估并向每个表增加主键之后,咱们往年切换了最初一个 SBR 正本集。应用 RBR 还为咱们提供了一个解决应用程序问题的代替解决方案,咱们在将一些正本集挪动到 8.0 主实例时遇到了这个问题,将在前面探讨。
4、自动化验证
大多数 8.0 迁徙过程都波及应用咱们的自动化架构和利用查问来测试和验证 mysqld 服务器。
咱们用来治理服务器的自动化基础架构在随着 MySQL 服务器的增长而增长。为了确保所有 MySQL 自动化组件都与 8.0 版本兼容,咱们投资构建了一个测试环境,该环境利用虚拟机上的测试正本集来验证行为。咱们为 canary 编写了在 5.6 版本和 8.0 版本上运行的每个自动化组件的集成测试,并验证了它们的正确性。在进行此演练时,咱们发现了几个谬误和行为差别。
当 MySQL 架构的每一部分都在咱们的 8.0 服务器上进行验证时,咱们发现并修复了(或解决了)一些乏味的问题:
解析谬误日志、mysqldump 输入或服务器 show 命令的文本输入的软件很容易损坏。服务器输入的轻微变动经常会暴露出工具解析逻辑中的谬误。
- 8.0 的默认 utf8mb4 排序规定设置导致 5.6 和 8.0 实例之间的排序规定不匹配。8.0 表可能会应用新的 utf8mb4_0900 排序规定,即便对于由 5.6 的 show create table 生成的 create 语句也是如此,因为应用 utf8mb4_general_ci 的 5.6 模式没有显式指定排序规定。这些表差别通常会导致复制和模式验证工具呈现问题;
- 某些复制失败的错误代码产生了变动,咱们必须修复咱们的自动化程序来正确处理它们;
- 8.0 版本的数据字典废除了 table.frm 文件,然而咱们的一些自动化零碎应用它们来检测表模式的批改;
- 咱们必须更新自动化零碎,以反对 8.0 中引入的动静权限。
5、利用程序验证
咱们心愿迁徙对应用程序尽可能通明,然而有些应用程序的查问会呈现性能进化,或者在 8.0 上会失败。
对于 MyRocks 迁徙,咱们构建了一个 MySQL 影子测试框架,该框架捕捉生产流量并将其重放到测试实例中。对于每个应用程序工作负载,咱们在 8.0 上创立了测试实例,并向它们回放影子流量的查问。咱们捕捉并记录了从 8.0 服务器返回的谬误,并发现了一些乏味的问题。可怜的是,并非所有这些问题都是在测试过程中发现的。例如,事务死锁是应用程序在迁徙过程中发现的。在钻研不同的解决方案时,咱们能够临时将这些应用程序回滚到 5.6 版本。
- 8.0 引入了新的保留关键字,其中一些关键字,如 groups 和 rank,与应用程序查问中罕用的表列名或别名相冲突。这些查问没有通过反引号本义名称,导致解析谬误。应用了主动本义查问中列名的软件库的应用程序没有遇到这些问题,但并非所有应用程序都应用这些软件库。解决这个问题很简略,然而须要工夫来跟踪生成这些查问的应用程序属主和代码库。
- 在 5.6 和 8.0 之间还发现了有些 REGEXP 不兼容。
- 一些蕴含在 InnoDB 上的 insert … on duplicate key 查问的应用程序遇到了 repeatable-read 事务死锁。5.6 有一个 bug,在 8.0 中失去了修复,然而修复减少了事务死锁的可能性。在剖析了查问之后,咱们可能通过升高隔离级别来解决该问题。这个选项对咱们来说是可用的,因为咱们曾经切换到基于行的复制。
- 咱们自定义的 5.6 文档存储和 JSON 函数与 8.0 不兼容。应用文档存储的应用程序须要将文档类型转换为文本以进行迁徙。对于 JSON 函数,咱们向 8.0 服务器中增加了兼容 5.6 的版本,以便应用程序当前能够迁徙到 8.0 API。
咱们对 8.0 服务器的查问和性能测试发现了一些须要立刻解决的问题。
- 咱们发现在 ACL 缓存局部呈现了新的互斥争用热点。当大量连贯同时关上时,它们都会阻塞 ACL 查看;
- 当存在大量 binlog 文件并且 binlog 的高速写入导致频繁轮换文件时,binlog 索引拜访也发现了相似的争用;
- 几个波及长期表的查问被中断。这些查问会返回意外谬误,或者运行工夫太长以至超时。
内存使用量与 5.6 相比有所增加,特地是对于 MyRocks 实例,因为必须加载 8.0 中的 InnoDB。默认的 performance_schema 设置启用了所有工具集并耗费了大量内存。咱们限度了内存应用,只启用了大量的工具,并对代码进行了更改,以禁用无奈手动敞开的表。
然而,并不是所有减少的内存都是调配给 performance_schema 的。咱们须要检查和批改各种 InnoDB 外部数据结构,以进一步缩小内存占用。这一致力使 8.0 的内存使用率降到了能够承受的程度。
6、接下来的工作
到目前为止,8.0 的移植曾经花了几年工夫。咱们已将许多 InnoDB 正本集转换为齐全在 8.0 上运行。剩下的大部分都处于迁徙路径的不同阶段。当初,咱们的大多数定制性能都已移植到 8.0,更新到 Oracle 的次版本绝对容易些,咱们打算跟上最新版本的步调。
跳过 5.7 这样的主版本会带来一些问题,咱们的迁徙须要解决这些问题。
首先,咱们无奈就地降级服务器,须要应用逻辑转储和还原来构建新服务器。然而,对于十分大的 mysqld 实例,这可能须要在沉闷生产服务器上运行很多天,而且这个软弱的过程可能会在实现之前被中断。对于这些大型实例,咱们必须批改备份和复原零碎来应答重建。
其次,检测 API 更改要艰难得多,因为 5.7 可能会向咱们的应用程序客户端收回不举荐正告,以提醒修复潜在的问题。而咱们须要在迁徙生产工作负载之前,运行额定的影子测试来查找失败。应用主动本义模式对象名称的 mysql 客户端软件,有助于缩小兼容性问题的数量。
在一个正本集中反对两个主版本十分艰难。一旦正本集将其主实例降级为 8.0,最好尽快禁用并移除 5.6 实例。应用程序用户往往会发现只有 8.0 反对的新个性,比方 utf8mb4_0900 排序规定,应用这些排序规定可能中断 8.0 和 5.6 实例之间的复制流。
只管咱们在迁徙过程中遇到了种种阻碍,但咱们曾经看到了运行 8.0 带来的益处。一些应用程序抉择了提前迁徙到 8.0,以利用诸如文档存储和改良的日期工夫反对等性能。咱们始终在思考如何在 MyRocks 上反对像即时 DDL 这样的存储引擎个性。总的来说,新版本大大扩大了 MySQL@Facebook 的性能。
作者 | Herman Lee,Pradeep Nayak
原文:https://engineering.fb.com/20…
译者 | 王雪迎 责编 | 晋兆雨
出品 | CSDN(ID:CSDNnews)
近期热文举荐:
1.1,000+ 道 Java 面试题及答案整顿 (2021 最新版)
2. 别在再满屏的 if/ else 了,试试策略模式,真香!!
3. 卧槽!Java 中的 xx ≠ null 是什么新语法?
4.Spring Boot 2.5 重磅公布,光明模式太炸了!
5.《Java 开发手册(嵩山版)》最新公布,速速下载!
感觉不错,别忘了顺手点赞 + 转发哦!