核心问题是连接未及时归还、复用错位或配置失衡,需查threads_connected与max_connections对比、show processlist识别sleep超时/慢查询/同host大量连接,并检查php层连接释放、超时参数匹配及慢事务。

PHP 8.0 网站数据库连接池满,核心问题不是“并发太高”,而是连接没及时归还、复用错位或配置失衡。重点看三点:是不是连接泄漏了、有没有慢查询/长事务卡住连接、连接池和数据库超时参数是否打架。
查当前真实连接状态
先登录 MySQL 执行以下命令:
- SHOW STATUS LIKE 'Threads_connected'; —— 看当前活跃连接数,对比 SHOW VARIABLES LIKE 'max_connections';
-
SHOW PROCESSLIST; —— 重点关注:
• Command = Sleep 且 Time > 60 秒的连接(大概率是泄漏或未优雅关闭)
• Command = Query 且 State 长时间卡在 Sending data 或 Sorting result(慢 SQL 占着连接)
• 同一 Host 出现大量 ID 不同的连接(说明应用在反复建连,可能健康检查失败或 DNS 缓存未刷新)
盯紧 PHP 层连接生命周期
PHP 8.0 下连接池满,90% 源于代码或配置没管住连接释放:
- 不用
Db::connect()或Cache::store('redis')这类工厂方法高频创建实例——它们每次返回新对象,不共享连接 - FPM 模式下禁用
PDO::ATTR_PERSISTENT,除非你确认 DSN 完全一致、且已处理事务/临时表残留问题 - 循环中查库必须复用同一个 PDO 实例,不要写
for (...) { new PDO(...) } - 确保异常路径也释放资源:用
try/finally显式调用$pdo = null或$stmt = null,别依赖 GC
核对连接池与数据库超时配置
两端超时不匹配,会制造“假连接”堆积:
- MySQL 的 wait_timeout(默认 28800 秒)必须比 PHP 连接池的 idle-timeout(如 HikariCP 的
idle-timeout: 600000)至少大 30 秒 - 若用 ProxySQL,确认
mysql-pool_enabled=1且mysql-default_max_connections_per_hostgroup已调高 - 开启连接有效性检测:
connection-test-query: SELECT 1+test-on-borrow: true,避免复用已断开的连接
抓慢查询和长事务放大效应
流量切换或压测时,原本不明显的 SQL 问题会被放大:
- 执行 SELECT * FROM information_schema.INNODB_TRX WHERE trx_started ,找运行超 30 秒的事务
- 打开 slow_query_log,阈值设为 1 秒,重点看切换后前 5 分钟新增的慢 SQL
- 检查新旧实例 buffer pool 大小是否一致,内存小会导致排序/临时表落盘,SQL 变慢,连接占用时间拉长
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











