frankenphp worker模式下连接数持续上涨的根因是worker常驻内存且php未主动断开mysql连接,导致每个worker绑定并长期持有数据库连接;必须禁用pdo::attr_persistent、设置mysql wait_timeout=60、frankenphp max-requests=500,并在代码中显式置空$pdo。

FrankenPHP Worker模式下连接数持续上涨的根因
不是MySQL扛不住,是Worker进程生命周期太长 + PHP代码没主动断开连接,导致每个Worker绑死一个MySQL连接不释放。FrankenPHP的Worker模式默认常驻内存、不重启,PDO或mysqli创建的连接会一直活在进程里,直到Worker被强制杀掉。
为什么禁用PDO::ATTR_PERSISTENT反而更关键
很多人以为“持久连接”能省开销,但在FrankenPHP Worker里它等于手动制造泄漏:一旦启用PDO::ATTR_PERSISTENT => true,连接就绑定到Worker进程,哪怕脚本执行完也不会关;下次请求复用时还可能残留autocommit=0或未提交事务,引发锁等待甚至死锁。
- Worker进程不销毁 → 持久连接永不释放
- 多个请求复用同一连接 → 事务状态/字符集/SQL_MODE可能错乱
-
wait_timeout(MySQL侧)远大于Worker存活时间 → MySQL不主动断,PHP也不管
结论:Worker模式下必须禁用PDO::ATTR_PERSISTENT,连配置都别出现这行。
三个必须改的配置项(FrankenPHP + MySQL协同)
光改PHP代码不够,MySQL和FrankenPHP的配合参数要对齐,否则“显式关闭”也白搭:
- MySQL端:
wait_timeout = 60和interactive_timeout = 60(写进my.cnf的[mysqld]段),让空闲连接60秒内被MySQL主动踢掉 - FrankenPHP Worker配置:
max-requests = 500(在frankenphp.yaml或命令行参数中设置),强制Worker处理500个请求后优雅退出,避免连接无限累积 - PHP代码里:每次用完
$pdo后加$pdo = null;,并确保没有全局/静态PDO实例跨请求存活
怎么确认是不是Worker连接泄漏而不是其他问题
别猜,直接查MySQL当前连接的来源和行为:
- 执行
SHOW PROCESSLIST;,重点看User列是否全是你的应用用户、Host是否集中在一个IP(比如FrankenPHP宿主机)、Command是否大量为Sleep、Time是否稳定在几百秒以上(说明没被回收) - 对比
SHOW STATUS LIKE 'Threads_connected';和SHOW STATUS LIKE 'Threads_running';:如果前者远大于后者(比如300 vs 2),基本锁定是Worker空闲连接堆积 - 检查FrankenPHP日志里有没有
worker exited或restarting worker记录,如果没有,说明Worker真的一路跑到底了
Worker模式的优势是低延迟,代价是连接管理责任完全移交给了你——它不会替你关数据库连接,也不会帮你重置事务状态。最易忽略的点:你以为return了,其实连接还挂在Worker进程的内存里。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











