workerman需惰性检测+按需重建数据库连接:在onworkerstart初始化单连接,执行sql时捕获2006/2013等错误码并重连一次,配合数据库wait_timeout设为60–300秒确保及时清理空闲连接。

Workerman 本身不提供数据库连接池,也不自动管理数据库连接的“有效性”,所谓“死连接”通常指 MySQL/Oracle 等数据库侧因网络中断、服务重启、超时断开后,Workerman 进程里还保留着一个已失效的 PDO 或 mysqli 句柄——后续调用 query() 会直接报错(如 MySQL server has gone away),但连接对象本身不抛异常,也不会自动重连。
解决思路不是靠“定时轮询清理”,而是**惰性检测 + 按需重建**。这是最轻量、最符合 Workerman 进程模型的做法。
为什么不用定时器主动 ping 所有数据库连接?
每个 Worker 进程只持有一个数据库连接(推荐做法),不存在“多个连接要轮询”的场景;定时 PING 会增加无谓 I/O,且无法覆盖真实 SQL 执行时的断连情况(比如中间网络闪断发生在两次 ping 之间);更关键的是,mysqli 或 PDO 的 ping() 方法在部分 PHP 版本或配置下不可靠(例如 MySQLi 的 ping() 在连接已关闭时可能不返回 false,反而触发 warning)。
onWorkerStart 中初始化连接并启用 auto-reconnect
在 onWorkerStart 回调里建立连接,并显式开启驱动层的自动重连能力:
魔搭GPT(ModelScopeGPT)是一款AI视频创作工具,阿里达摩院推出的大小模型协同的智能助手,具备作诗、绘画、视频生成、语音播放等多模态能力。
-
PDO:设置PDO::ATTR_EMULATE_PREPARES => false和PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4",但注意PDO::ATTR_ERRMODE必须设为PDO::ERRMODE_EXCEPTION,否则错误不会抛出 -
MySQLi:调用$mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 3)并确保mysqli.reconnect = On在 php.ini 中启用(PHP 7.0+ 默认开启) - 不要把连接存在
static或全局变量里跨进程共享,每个 Worker 自己管自己的连接
执行 SQL 时捕获死连接错误并重试
真正可靠的检测时机是执行 SQL 的瞬间。遇到典型死连接错误码,就销毁旧连接、重建新连接、重试一次:
- MySQL 常见错误码:
2006(MySQL server has gone away)、2013(Lost connection to MySQL server during query) - 在封装的数据库操作方法中(如
db_query()),用try-catch包裹execute()或query() - 捕获到上述错误码后:
unset($this->pdo)或$mysqli->close(),再调用初始化逻辑重建连接,然后重试原 SQL - 最多重试 1 次,避免无限循环;重试前可加
usleep(10000)避免雪崩
配合数据库端 idle_timeout 限制更稳妥
光靠应用层不够,必须让数据库主动切断空闲太久的连接,防止连接堆积:
- MySQL:设置
wait_timeout和interactive_timeout(建议 60–300 秒),通过SHOW VARIABLES LIKE '%timeout%'查看 - Oracle:用
PROFILE设置IDLE_TIME,如create profile killidle limit idle_time 30;,再绑定到应用用户 - PostgreSQL:调整
tcp_keepalives_idle、tcp_keepalives_interval等参数,或依赖 OS 层 keepalive - 这些设置能让数据库在连接空闲超时后主动
KILL,此时下一次应用层 SQL 执行必然失败,从而触发上面的重连逻辑
Workerman 是多进程,每个进程独立重连没问题)、以及**数据库端 timeout 与应用层重试间隔是否形成安全覆盖**。漏掉一个错误码,或者数据库没配 timeout,死连接就会悄悄积累。










