跳转到内容
搜索文档

故障排除与调试

最后更新 查看 MarkdownAgent 设置

排查和调试使用 Hyperdrive 连接数据库时常见的错误。

配置错误

创建新的 Hyperdrive 配置,或更新现有配置的连接参数时,Hyperdrive 会在后台对数据库执行测试连接,然后再创建或更新配置。

Hyperdrive 还会发出空测试查询(PostgreSQL 中为 ;),以验证能否将查询传递到数据库。

错误代码 详情 建议修复
2008 主机名无效。 Hyperdrive 无法解析数据库主机名。确认其在公网 DNS 中存在。
2009 主机名未解析为公网 IP 地址,或 IP 地址不是公网地址。 Hyperdrive 只能连接公网 IP 地址。目前不支持 10.1.5.0192.168.2.1 等私有 IP 地址。
2010 无法连接到 host:port。 Hyperdrive 无法路由到主机名:确保其有解析为公网 IP 的公网 DNS 记录。检查主机名是否拼写错误。
2011 连接被拒绝。 网络防火墙或访问控制列表(ACL)可能拒绝了来自 Hyperdrive 的请求。确保已允许来自公网的连接。
2012 数据库不支持 TLS(SSL)。 Hyperdrive 连接需要 TLS(SSL)。请在数据库上配置 TLS。
2013 数据库凭据无效。 确保用户名正确(且存在),密码正确(区分大小写)。
2014 指定的数据库名称不存在。 检查你提供的数据库(非表)名称是否存在于 Hyperdrive 要连接的数据库上。
2015 通用错误。 Hyperdrive 连接失败且无法确定原因。请提交支持工单以便 Cloudflare 调查。
2016 测试查询失败。 确认 Hyperdrive 连接使用的用户对给定数据库具有读写查询权限。

连接失败

尝试创建 Hyperdrive 配置时,Hyperdrive 也可能发出 Failed to connect to the provided database(无法连接到提供的数据库)。当 TLS(SSL)证书配置错误时可能出现此情况。以下是连接失败错误的非详尽列表:

错误消息 详情 建议修复
Server return error and closed connection. 尝试连接启用了客户端证书验证的数据库时出现此消息。 若数据库需要客户端证书,请确保 Hyperdrive 配置了客户端证书
TLS handshake failed: cert validation failed. 当 Hyperdrive 配置了服务器 CA 证书,且表明服务器提供的证书未被预期的 CA 证书签名时出现此消息。 确保 Hyperdrive 使用正确的 CA 证书,或确保连接的是正确的数据库。

连接错误

Hyperdrive 还可能在运行时返回错误。这可能发生在初始连接建立期间,或响应驱动发送的查询或其他 wire 协议命令时。

这些错误以 ErrorResponse wire 协议消息返回,大多数驱动通过从相关查询抛出异常或触发 error 事件来处理。 未与 PostgreSQL 文档 中记录的错误消息代码一一对应的 Hyperdrive 错误使用 58000 错误代码。

Hyperdrive 还可能遇到数据库发送的 ErrorResponse wire 协议消息。Hyperdrive 会在可能的情况下原样传递这些错误。

Hyperdrive 特定错误

错误消息 详情 建议修复
Internal error. Cloudflare 端出现问题。 检查是否有影响 Hyperdrive 的持续事件,并联系 Cloudflare 支持。若符合使用模式,可重试查询。
Failed to acquire a connection from the pool. Hyperdrive 等待数据库连接超时,或完全无法连接。 若此错误间歇出现,Hyperdrive 连接池已耗尽,因为 Worker 持有过多连接时间过长。可能由多种问题引起,但长时间运行的查询/事务是常见原因。
Server connection attempt failed: connection_refused Hyperdrive 无法创建到源数据库的新连接。 网络防火墙或访问控制列表(ACL)可能拒绝了来自 Hyperdrive 的请求。确保已允许来自公网的连接。有时,当超出连接限制时,数据库主机提供商可能拒绝传入连接。
Hyperdrive does not currently support MySQL COM_STMT_PREPARE messages Hyperdrive 不支持 MySQL 数据库的预处理语句。 从 MySQL 查询中移除预处理语句。

Node 错误

错误消息 详情 建议修复
Uncaught Error: No such module "node:<module>" Cloudflare Workers 项目或其导入的库尝试访问不可用的 Node 模块。 为 Cloudflare Workers 项目启用 Node.js 兼容性 以最大化兼容性。

写入后读取到旧数据

若应用写入数据后后续读取返回较旧数据,Hyperdrive 查询缓存可能正在提供缓存的读查询结果。按 cacheStatus 检查 Hyperdrive 指标,确认读取返回 hitmissdisableduncacheable。请参阅指标与分析

要解决写入后读取到旧数据的问题,请参阅查询缓存指南,了解如何将新鲜读取与可缓存读取分离,包括为必须返回新鲜数据的读取使用禁用缓存的 Hyperdrive 配置。

未缓存的查询

若 Hyperdrive 已启用缓存但查询未被缓存,请检查以下项:

  • 查询中包含稳定或易变 PostgreSQL 函数:包含分类为 STABLEVOLATILE 的 PostgreSQL 函数的查询不可缓存。常见示例包括 NOW()CURRENT_TIMESTAMPCURRENT_DATERANDOM()LASTVAL()。解决方法是将函数调用移至应用代码并将结果作为查询参数传递。例如,不要写 WHERE created_at > NOW(),而是在 Worker 中计算时间戳并作为参数传递:WHERE created_at > $1。请参阅查询缓存获取完整的不可缓存函数列表。

  • SQL 注释中的函数名称:Hyperdrive 使用基于文本的模式匹配来检测某些不可缓存函数。SQL 注释中对 NOW() 等函数名称的引用可能导致查询被视为不可缓存,即使函数未被实际调用。从查询文本(包括注释)中移除对不可缓存函数名称的引用。

  • 驱动配置:驱动可能配置为 Hyperdrive 无法缓存查询。例如,使用 Postgres.js 驱动并设置 prepare: false 时可能发生。解决方法是使用 prepare: true 启用预处理语句。

驱动错误

错误消息 详情 建议修复
Code generation from strings disallowed for this context 你使用的数据库驱动尝试使用 eval() 命令,Cloudflare Workers 不支持(mysql2 驱动中常见)。 配置数据库驱动不使用 eval()。请参阅如何配置 mysql2 禁用 eval() 用法

陈旧连接和 I/O 上下文错误

当数据库客户端或连接在全局作用域(请求处理程序之外)创建,或在请求间复用时,会出现这些错误。Workers 不允许跨请求 I/O,来自先前请求上下文的数据库连接将不可用。始终在处理程序内创建数据库客户端

Workers 运行时错误

错误消息 详情 建议修复
Disallowed operation called within global scope. Asynchronous I/O (ex: fetch() or connect()), setting a timeout, and generating random values are not allowed within global scope. Worker 在脚本启动期间(请求处理程序之外)尝试打开数据库连接或执行 I/O。 将数据库客户端创建移至 fetchqueue 或其他处理程序函数中。
Cannot perform I/O on behalf of a different request. I/O objects (such as streams, request/response bodies, and others) created in the context of one request handler cannot be accessed from a different request's handler. 在一个请求期间创建的数据库连接或客户端在后续请求中被复用。 每个请求创建新的数据库客户端,而非缓存在全局变量中。Hyperdrive 的连接池已消除连接启动开销。

node-postgres(pg)错误

错误消息 详情 建议修复
Connection terminated 调用了客户端的 .end() 方法,或连接在先前请求结束时被清理。 在处理程序内创建新的 Client,而非复用先前请求的客户端。
Connection terminated unexpectedly 底层连接在没有显式 .end() 调用的情况下断开——例如,先前请求的上下文被垃圾回收时。 每个请求在处理程序内创建新的 Client
Client has encountered a connection error and is not queryable 连接上发生套接字级错误(跨请求复用客户端时常见)。 在处理程序内创建新的 Client。不要将客户端存储在全局变量中。
Client was closed and is not queryable 在已调用 .end() 的客户端上尝试查询。 在处理程序内创建新的 Client,而非复用已有客户端。
Cannot use a pool after calling end on the pool 在已结束的 Pool 实例上调用 pool.connect() 不要在全局作用域使用 new Pool()。在处理程序内创建 new Client()——Hyperdrive 会为你处理连接池。
Client has already been connected. You cannot reuse a client. 在先前调用中已连接的客户端上调用 client.connect() 每个请求创建新的 Client。node-postgres 客户端连接后无法重新连接。

Postgres.js(postgres)错误

Postgres.js 错误消息包含错误代码和目标主机。错误对象的 code 属性包含错误代码。

错误消息 详情 建议修复
write CONNECTION_ENDED <host>:<port> 在调用 sql.end() 后或连接从先前请求清理后尝试查询。错误代码:CONNECTION_ENDED 在处理程序内创建新的 postgres() 实例。
write CONNECTION_DESTROYED <host>:<port> 连接被强制终止——例如在 sql.end({ timeout }) 过期期间,或因为连接已被终止。错误代码:CONNECTION_DESTROYED 每个请求在处理程序内创建新的 postgres() 实例。
write CONNECTION_CLOSED <host>:<port> 底层套接字在仍有待处理查询时意外关闭。错误代码:CONNECTION_CLOSED 在处理程序内创建新的 postgres() 实例。若此错误在单个请求内出现,请检查网络问题或查询超时。

mysql2 错误

错误消息 详情 建议修复
Can't add new command when connection is in closed state 在已关闭或遇到致命错误的连接上尝试查询。 在处理程序内创建新连接,而非从全局作用域复用连接。
Connection lost: The server closed the connection. 底层套接字被服务器关闭或在请求间被垃圾回收。错误代码:PROTOCOL_CONNECTION_LOST 每个请求在处理程序内创建新连接。
Pool is closed. 在已关闭的连接池上调用 pool.getConnection() 不要在全局作用域使用 createPool()。在处理程序内创建新的 createConnection()——Hyperdrive 会为你处理连接池。

mysql 错误

错误消息 详情 建议修复
Cannot enqueue Query after fatal error. 在先前遇到致命错误的连接上尝试查询。错误代码:PROTOCOL_ENQUEUE_AFTER_FATAL_ERROR 在处理程序内创建新连接,而非从全局作用域复用连接。
Cannot enqueue Query after invoking quit. 在调用 .end() 后的连接上尝试查询。错误代码:PROTOCOL_ENQUEUE_AFTER_QUIT 每个请求在处理程序内创建新连接。
Cannot enqueue Handshake after already enqueuing a Handshake. 在先前请求中已连接的连接上调用 .connect()。错误代码:PROTOCOL_ENQUEUE_HANDSHAKE_TWICE 每个请求创建新连接。mysql 连接连接后无法重新连接。

提升性能

将查询流量写为事务可能限制性能。因为在事务情况下,连接必须在整个事务期间保持,这会限制连接多路复用。若每个事务包含多个查询,对连接多路复用的影响可能尤为显著。建议在可能的情况下不要将查询包装在事务中,以便更积极地共享连接。

这篇文档对您有帮助吗?