故障复盘:PHP 和 MariaDB Docker 问题

多年前,我和我的孩子们(现在他们都长大了)一起看了一部名为《拜访罗宾逊一家》的电影。电影中贯穿始终的主题是,犯错误是可以的,因为我们可以从错误中学习,并“继续前进”。

不幸的是,几个问题凑巧同时发生,导致 2024 年 2 月 21 日,mariadb:latest Docker 镜像无法与 PHP 和 NodeJS 客户端一起工作。现在,我在 MariaDB 基金会帮忙引入的一件事就是进行故障复盘的概念,不仅仅是在事情出错时,也在事情顺利时进行。这些复盘不是为了找出谁的错,也不是为了推卸责任。而是为了找出流程中的缺陷,正是这些缺陷导致了问题的发生,这样我们才能学习不再重蹈覆辙。为了制定措施防止再次发生。我们实际上会在每个发布周期都进行复盘,记录发生的事情,并看看是否有可以自动化和改进的地方。

在这种情况下,它影响了许多使用 Docker 获取 MariaDB 服务器的 PHP 应用程序用户。所以,我认为我们应该尽可能透明地说明发生了什么,我们如何解决的,以及我们打算如何阻止它在未来再次发生。

话不多说,让我们深入探讨。

前言

mariadb:latest Docker 更新到 11.3 版本,其中包含 Debian 软件包的默认排序规则配置文件更改。该排序规则触发了 PHP mysqlnd 和 NodeJS 连接器中的一个 bug,导致应用程序无法登录。

在 MySQL 4.0 中,服务器将默认排序规则作为 1-255 范围内的单字节 ID 发送到客户端。在 MySQL 4.1(2003 年发布)中,这种通信方向发生了改变,现在是客户端到服务器,但为了兼容性,服务器到客户端的通信仍然受支持,并且一直延续至今。MariaDB 的新排序规则使用的 ID 高于 255,因此兼容性排序规则字节以零开头,并在其他地方使用扩展字节。

Debian 软件包中的配置文件在 PR 2775 中更新,使用了更现代的默认服务器排序规则,该 PR 已在 11.3 版本中合并。PHP 的 mysqlnd 和 NodeJS 的连接器仍然验证服务器排序规则,当它们看到零时,就会生成一个错误。这个错误会中止身份验证过程。

事件序列

为了阐明发生了什么,以下是对事件的详细记述。如果您对全局感兴趣,请随时跳到“原因”标题。

提供的时间均为 UTC 时间。

2023-10-19

一个合并请求被合并,该请求更改了 Debian 软件包配置文件中的默认服务器排序规则。注意:MariaDB Docker 镜像使用 Debian 打包。

2023-12-08

Jira MDEV-32975 已开启,用户发现上述提交在使用 MariaDB 11.3.1 的 Debian 软件包时破坏了 PHP 应用程序。

2024-01-26

Alexander Barkov 创建了一个兼容性补丁作为 MDEV-32975 的解决方案,并提交进行代码审查。

2024-02-20 23:45

MariaDB Docker 镜像已更新,使 mariadb:latest 指向 11.3.2 而不是 11.2.3,因为这是 MariaDB 新的最新稳定版本。

2024-02-21 07:34

社区用户在 MariaDB Docker 上开启了一个 issue,该用户在使用 Docker 镜像时遇到了身份验证问题。

2024-02-21 09:44

社区用户出于同样原因在 PHP 项目 GitHub 上开启了一个 issue

2024-02-21 10:21

Andrew Hutchings 通过 Twitter 收到了问题警报并开始调查。

2024-02-21 10:34

Vicențiu Ciorbaru(通过 Docker GitHub issue 注意到问题)和 Andrew 同时内部通知了基金会其他员工。

2024-02-21 11:32

Andrew 已经确定问题原因即MDEV-32975。他请求将其升级为 Blocker(阻止)状态(立即得到批准)。向 MariaDB 核心开发人员沟通了严重性变更的原因。

2024-02-21 11:52

经过一些内部讨论后,Andrew 在 MariaDB Docker GitHub 议题上发布了一个临时解决方案。半小时内,社区进行了测试,似乎是成功的。

2024-02-21 16:59

经过大量研究和讨论,Andrew 弄清了根本原因的细节,他更新了 PHP 议题,提供了详细信息,导致该议题被重新开启。

2024-02-21 17:45

在他一天结束时,Andrew 内部将目前为止的所有信息传递给了团队的其他成员,但他继续协助社区成员解决这个问题直到深夜。他后来向团队沟通发现 NodeJS 也受到了影响。

2024-02-21 21:56

Daniel Black 负责 MariaDB Docker 镜像的管理,他上线并开始着手解决问题。

2024-02-21 22:50

Daniel 打开了 CONJS-281 来处理 NodeJS 的问题。

2024-02-22 00:52

Daniel 在 MariaDB 的 Docker 仓库中开启了一个合并请求来临时解决这个问题。

2024-02-22 01:06

Daniel 为 Docker 创建了一个合并请求,该请求指向带有临时解决方案的 MariaDB Docker 更新。4 分钟后,该请求被合并。

2024-02-22 04:43

更新后的 Docker 镜像已发布到 Docker Hub。

2024-02-22 05:04

MariaDB Docker GitHub 议题被标记为关闭。之后进行了外部沟通。

原因

不幸的是,几个问题凑巧同时发生,导致了这个问题。如果其中任何一个问题没有发生,我们都不会遇到这些麻烦。

  1. PHP mysqlnd 和 NodeJS 连接器试图验证一个已经 20 年未使用的字节上的数据。这对我们来说是出乎意料的,但可以理解这个检查从未被移除。
  2. 这个 bug 实际上通过 MDEV-32975(默认字符集不兼容 PHP MySQLi 扩展)得到了修复,但是这个补丁在 11.3 GA 之前没有经过审查,所以它不在代码库中。
  3. 上述两个因素的结合导致 PR 2775 (MDEV-32336 deb 默认配置 – 使用 collation-server = utf8mb4_uca1400_ai_ci) 中的配置变更导致了故障。
  4. 我们有可以及早发现此问题的 CI 测试,但 MDBF-637(由于 reprepro 缺少 debuginfo 软件包)意味着相关的 CI 构建器目前处于损坏状态。

见解

  1. WordPress 和 Nextcloud 社区在遇到问题时反应和沟通非常及时。
  2. 11.3 的 Debian 软件包仍然受到影响,根据当前的发布模型,将不再有 11.3 的后续版本发布,因此此问题将在 11.4 中修复。
  3. 我们确实有流程来避免和检测类似的问题,但当事态变得糟糕时,流程确实会失效。

建议

以下是我们正在实施的建议,以正确解决此问题并阻止未来发生类似情况。

  1. MDEV-32975 的补丁需要被审查和合并,如果需要更多工作,则需要纠正后合并。
  2. 11.3 的发布说明需要更新,以通知可能受此影响的 Debian 用户,并说明如何实施临时解决方案。
  3. 我们需要修复 MDBF-637,确保可以捕获此问题的测试能够运行,并使 amd64-rhel8-wordpress 成为合并请求的必需测试项。
  4. 我们应该通过博客文章(即此博客文章)将本次故障复盘公开。

结论

希望这篇文章能够让您了解 MariaDB Server 版本发布时出现问题后会发生什么。我们要感谢社区的快速报告、响应和反馈。没有你们,我们不可能这么快解决问题。

特色图片来自 Digits.co.uk,在 CC 许可下使用。

发布者:Andrew Hutchings

MariaDB 基金会首席贡献官