FrankenPHP在Worker模式下需显式启用PDO持久连接并禁用自动关闭,否则连接快速耗尽;MySQL须调大max_connections及账号限制,并手动清理事务与连接以防泄漏。

FrankenPHP 本身不直接管理数据库连接,它只负责运行 PHP 应用;数据库配置完全由你的 PHP 框架或应用代码决定。关键在于:**在 Worker 模式下,必须显式启用持久连接,并禁用自动关闭行为**,否则连接会快速耗尽。
确认是否启用 Worker 模式
FrankenPHP 的数据库连接问题几乎全部集中在 php_worker 启用后。如果你只是用 FrankenPHP 当普通服务器(没加 worker 命令),那和传统 PHP-FPM 行为一致,无需特殊处理。但一旦使用:
frankenphp worker index.php- 或 Docker 中设
FRANKENPHP_WORKER_ENTRYPOINT=index.php
——就进入了常驻进程模式,PDO 实例会被复用,此时必须按 Worker 场景配置。
框架层开启持久连接
不同框架写法不同,但核心都是传递 PDO::ATTR_PERSISTENT => true:
立即学习“PHP免费学习笔记(深入)”;
-
ThinkPHP:在
config/database.php中设'persistent' => true -
Laravel:在
.env加DB_PERSISTENT=true;同时确保doctrine.dbal.auto_close=false(避免框架主动 close) -
Symfony/Doctrine:在
config/packages/doctrine.yaml的 connection options 中加入:pdo::ATTR_PERSISTENT: true -
原生 PDO:必须手动传参,不能只写
new PDO($dsn, $user, $pass),要写成:new PDO($dsn, $user, $pass, [PDO::ATTR_PERSISTENT => true])
MySQL 侧配合调优
光配 PHP 不够,MySQL 必须留出足够余量:
- 查当前连接数:
SHOW GLOBAL STATUS LIKE 'Threads_connected'; - 查上限:
SHOW VARIABLES LIKE 'max_connections'; - 起步建议值:
max_connections = (num_threads × 4) + 16(例如 FrankenPHP 设了num_threads=8,则 MySQL 至少设48) - 检查账号级限制:
SELECT user, host, max_connections FROM mysql.user;,尤其注意应用专用账号是否被max_user_connections卡住
防泄漏与事务清理
Worker 复用意味着上一个请求的事务、prepare 语句、未释放的句柄可能污染下一个请求:
- 所有手动获取 PDO 实例的地方(如
DB::connection()->getPdo()),用完后必须unset($pdo)或置为null - 避免在循环中反复打开连接;如有必要,确保每个连接都在
try/finally块中显式释放 - 不要依赖
wait_timeout自动断连——Worker 进程长期存活,空闲连接不会被回收 - 开启慢日志 + 连接数监控:
netstat -an | grep :3306 | wc -l,持续上涨就是泄漏信号



















