




PHP MySQLi 长连接需在主机名前加 p: 前缀(如 'p:127.0.0.1'),仅面向对象风格有效;PDO 则需设置 PDO::ATTR_PERSISTENT => true,但在 PHP-FPM 下才较可靠,且须注意事务、字符集等上下文污染问题。
MySQLi 默认不启用长连接,必须显式传参 MYSQLI_CLIENT_FOUND_ROWS 以外的标志位——关键是加 MYSQLI_CLIENT_INTERACTIVE 或直接用 MYSQLI_OPT_CONNECT_TIMEOUT 配合连接复用逻辑,但更可靠的方式是使用 mysqli::real_connect() 并设置 MYSQLI_CLIENT_COMPRESS | MYSQLI_CLIENT_INTERACTIVE。不过实际中,真正起作用的是在 DSN 或连接参数里带上 p: 前缀(仅限 mysqli 面向对象风格或 mysqlnd 驱动)。
常见错误:以为只要把 mysql_connect() 换成 mysqli_connect() 就自动长连接——其实旧函数已废弃,新函数默认仍是短连接。
new mysqli('p:127.0.0.1', ...),主机名前加 p: 是关键p: 前缀,必须改用 mysqli_init() + real_connect()
mysqlnd 扩展必须启用(PHP 5.4+ 默认开启),否则 p: 无效PDO 的 PDO::ATTR_PERSISTENT => true 看似简单,但实际效果受限于底层驱动和 Web SAPI 环境。在 CLI 下几乎无效,在 Apache mod_php 下表现不稳定,在 PHP-FPM 下才较可靠——因为连接复用依赖于 worker 进程的存活时间。
容易踩的坑:PDO::ATTR_PERSISTENT 不会自动清理事务、临时表、用户变量等上下文状态,上一个请求留下的 SET NAMES utf8mb4 或未提交事务可能污染下一个请求。
立即学习“PHP免费学习笔记(深入)”;
$pdo->beginTransaction() / $pdo->rollBack() 或执行 RESET QUERY CACHE 类语句(不推荐)USE DB_NAME 切库,应统一用带库名的表引用(如 db1.users)wait_timeout 控制,PDO 层无法绕过,需确保该值 ≥ PHP-FPM max_request
SHOW PROCESSLIST 观察 Command 列是否为 Sleep 且 Time 持续增长根本原因往往不在 PHP 配置,而在 MySQL 服务端或中间件限制。最常见的是:PHP-FPM 子进程被 pm.max_requests 强制回收、MySQL 的 wait_timeout(默认 28800 秒)先于 PHP 进程失效、或负载均衡器(如 Nginx)主动断开空闲连接。
child exited 记录,确认是否因 max_requests 触发重启SELECT @@wait_timeout, @@interactive_timeout,二者都需调大(例如设为 3600)proxy_read_timeout 和 keepalive_timeout 必须 ≥ MySQL wait_timeout
SELECT 
1)不需要,也不应该调用 mysqli_close() 或 $pdo = null。长连接的设计本意就是让连接留在进程内存中复用;手动关闭反而触发重建,失去意义。PHP 请求结束时,若启用了持久化机制,连接会被归还到连接池而非销毁。
但要注意:如果代码中存在 unset($mysqli) 或异常提前退出未捕获,可能导致连接句柄泄露(尤其在 PHP-FPM 中表现为 Too many connections 错误)。
mysqli_close($link)
Threads_connected 和 Threads_created,比值持续接近 1 表示长连接生效