本文目录导读:

在PHP开发中,选择长连接还是短连接,没有一个绝对的答案,核心取决于你的业务场景、并发量、以及对资源的掌控能力。
大多数常见的PHP Web应用(特别是使用Apache或标准Nginx/FPM)天然更适合短连接。 只有特定高并发、低延迟的场景才需要引入长连接(通常是常驻内存的进程)。
下面从几个核心维度帮你做决策:
核心区别速览(以MySQL为例)
| 特性 | 短连接 | 长连接 |
|---|---|---|
| 连接创建 | 每次请求都经历 TCP 三次握手 + MySQL认证 | 连接复用,创建后长时间保持不断开 |
| 资源消耗 | 每次建立连接消耗 CPU 和内存,但释放也快 | 初期消耗大,后期稳定,容易积累资源(内存、MySQL连接数) |
| PHP生命周期 | 与每次HTTP请求同生共死(PHP-FPM进程处理完就销毁) | 需要常驻内存的进程(如Swoole、Workerman)才能发挥效果 |
| 适用模型 | 传统的 LAMP/LNMP(Apache/Nginx + PHP-FPM) | 基于事件驱动的异步/协程模型(Swoole、Hyperf、ReactPHP) |
| 典型代码 | mysqli_connect() 用完后 close() |
连接池对象,代码中断开但进程不断 |
什么时候选短连接?(95%的情况选这个)
你的环境是:Apache / Nginx + PHP-FPM / mod_php
- 原因:PHP-FPM 是“短命”进程,每个请求都会 fork 一个 PHP 进程,处理完就销毁,在这个模型下使用长连接是灾难。
- 问题:
- 请求A创建了长连接,进程结束时不销毁。
- 请求B来了,PHP-FPM 可能复用同一个进程(FPM有进程池),此时旧连接可能已经超时断开了,导致复用一个死连接,报错
MySQL has gone away。 - 需要额外编写复杂的
pconnect维护代码(检查、重连)。 - 费劲不讨好,性能提升有限,问题却很多。
你的QPS(每秒请求数)不高(< 1000)
- MySQL建立连接一次通常需要1-3ms,占总请求时间的比例很小,为了省下这1ms而引入复杂的连接管理,得不偿失。
你的后端服务像“短跑运动员”
- 处理请求逻辑复杂,耗时几十毫秒到几秒,在这种情况下,连接建立的耗时占比甚至可以忽略不计。
什么时候选长连接?(4%的情况选这个)
你的环境是:Swoole / Workerman / ReactPHP
- 核心原因:这些框架是常驻内存的,进程或协程在处理完一个请求后不会退出,会继续监听下一个请求。
- 效果:连接建立后可以无限复用,彻底消除了每次请求的TCP握手和MySQL认证开销,长连接+连接池可以有效控制与MySQL的连接总数(比如一个Swoole Worker进程只维持1-2个MySQL连接,而不是每个请求都开一个)。
你追求极致的低延迟和高并发(QPS > 5000)
- 在高并发场景下,短连接会频繁地创建和销毁TCP连接,可能导致系统负载变高,并会占用大量MySQL服务器的文件描述符和线程资源,长连接配合连接池可以平滑应对。
你是纯后端服务(API)、微服务、RPC服务
- 业务主要是内部模块之间的高并发数据交换,不需要像Web页面那样面向大量未知用户的短暂访问。
结论与实践建议
| 你的场景 | 推荐方案 | 坑与技巧 |
|---|---|---|
| 传统Web开发 (ThinkPHP, Laravel, WordPress) | 短连接 | 使用数据库连接池中间件(如ProxySQL)来缓解PHP短连接对MySQL的压力,而不是在PHP代码里用pconnect。 |
| API/微服务/SDK | 长连接 | 必须搭配连接池(如Swoole连接池、Hyperf连接池),并设置心跳检测防止连接断开。 |
| CLI脚本 | 建议短连接(或显式关闭) | 长时间运行的CLI脚本如果在结束时忘记关闭连接,会导致MySQL连接一直等待。 |
| 测试环境 | 短连接 | 省心,不易出bug。 |
PHP中的“伪长连接” pconnect 要谨慎使用
PHP内置的 mysql_pconnect 或 mysqli 的 p:host 前缀是进程级的。
- 在PHP-FPM中:它只是进程池复用,假设你有50个FPM Worker进程,最多只会建立50个MySQL连接,当一个请求使用完后,并不关闭连接,而是归还给进程,下一个同进程的请求可以直接复用。
- 问题:
- 并发瓶颈:如果同时有100个并发请求,但只有50个FPM进程在工作,可能会导致50个请求等待空闲进程,而MySQL的连接只有50个。
- 状态隔离难题:最危险的是,如果你在事务或临时表操作中错误地复用了连接,下一个请求进来会看到上一个请求未提交或回滚的数据。
- 内存泄漏:连接状态(如字符集、SQL模式)可能被污染。
最终建议:
- 对于99%的PHP开发者:用短连接(普通
new mysqli()或PDO),不需要纠结。 - 如果必须用长连接(比如你改用Swoole),一定配套成熟的连接池库(如
hyperf/pool、think-orm的连接池支持),而不要自己手写pconnect。 - 监控是关键:无论长短,都要监控MySQL的
Threads_connected和Aborted_connects。
一句话总结: 你的开发框架决定了连接策略,如果你在用ThinkPHP/Laravel + PHP-FPM,坚决用短连接;如果是Hyperf/Swoole + 常驻内存,必须用长连接+连接池。