Cloudflare 宣布 Hyperdrive 中的 MySQL 支持正式可用。Hyperdrive 是一项面向 Workers 用户的服务,用于通过 Cloudflare 的网络集中并复用数据库连接。此次从测试版转为正式可用,是在处理了约 20 个故障之后进行的,其中包括一个罕见的查询结果缓存问题,该问题会在预期存在数据的情况下导致空响应。
该问题的发生率约为 0.001%,因此很难通过跟踪日志发现。Cloudflare 发现,只有启用缓存时才会出现这一故障;该问题由测试阶段使用 MySQL 服务最多的客户报告。
Hyperdrive 如何工作?
Hyperdrive 会在 Cloudflare 网络中保持 SQL 连接处于活跃和开放状态,然后在多个 Workers 请求之间共享这些连接,而不是为每个请求创建新连接。它还可以将常见查询的结果存储在本地 CDN 缓存中,从而减少延迟以及对源数据库的压力。
该服务的架构由一个靠近 Worker 运行的 Client 节点,以及一个负责管理连接池的 Endpoint 节点组成;后者位于靠近源数据库的数据中心。当两个节点在同一个数据中心运行时,它们可以共享同一个缓存。
故障源于 MySQL 协议格式差异
Hyperdrive 从两个不同方向处理 MySQL:它作为 Worker 前面的服务器运行,同时又作为源数据库前面的客户端运行。由于 Worker 协商出的协议能力可能不同于 Hyperdrive 与数据库使用的协议能力,因此该服务必须重新格式化结果消息,以适配最终客户端。
调查重点在于结果集的结束方式。一些 MySQL 库(包括 Node.js 中常用的 mysql2 库)不支持 CLIENT_DEPRECATE_EOF 能力。缺少该能力时,服务器会使用 EOF 数据包;而较新的协议行为则会在结果集末尾使用 OK 数据包取代 EOF 数据包。
Client 节点有时会存储经过转换、以适配 Worker 能力的字节,而 Endpoint 节点则预期获得符合 Hyperdrive 能力的标准版本。当其中一个节点读取另一个节点存储的结果时,可能会以不匹配的格式处理消息,从而导致提前出现 EOF、挂起或空结果。
实际发生了哪些变化?
Cloudflare 通过让所有节点将查询结果的标准版本写入缓存来修复该问题。无论由哪个节点进行缓存,该版本始终按照 Hyperdrive 的能力进行编码。修复发布后,空行问题消失,Client 连接成功率达到 99.99%,Cloudflare 表示。
该公司还处理了测试期间出现的其他问题,包括表情符号编码错误。使用 utf8 实际上指向的是 utf8mb3,后者不支持所有四字节 Unicode 码点。该服务已改用 utf8mb4。此外,在执行 COM_RESET_CONNECTION 命令后,服务会重新设置编码,因为该命令会将连接恢复为服务器的默认设置,而该设置可能是 latin1。
可用性与限制
MySQL 支持现已通过 Cloudflare 控制面板或 wrangler 工具正式提供,可与兼容 MySQL 的数据库配合使用,包括连接到新的 PlanetScale 数据库。这一情况表明,中间层中的连接池和缓存不仅依赖 SQL 的正确性,还要求协议状态与各层所预期格式之间实现精确匹配。