Composer镜像源并发构建时MySQL连接数被打满,根本原因是镜像服务后端未启用连接池或限流,高并发HTTP请求(如/packages.json、/p2/xxx.json)触发大量PDO短连接,瞬间耗尽MySQL的max_connections。

Composer镜像源并发构建时MySQL连接数被打满
这不是 Composer 本身的问题,而是镜像服务后端(如私有 Packagist 镜像)在高并发 composer install 请求下,对数据库的连接池未做限流或复用,导致 MySQL 的 max_connections 被瞬间耗尽,报错类似 Too many connections 或直接拒绝新连接。
为什么镜像源会触发数据库连接风暴
每次 composer install(尤其是首次或无 composer.lock 时)会向镜像源发起大量 /packages.json、/p2/xxx.json、/downloads/xxx.zip 等请求。现代镜像服务(如 Satis、Private Packagist、Artifactory 插件)多数将包元数据缓存在 MySQL 中,并为每个 HTTP 请求新建 PDO 连接——若未配置连接复用或连接池,100 个并发请求 ≈ 100 个 DB 连接。
- CI/CD 中常见场景:GitHub Actions 并发运行 5+ jobs,每个 job 执行
composer install,全部打到同一镜像域名 - 本地开发误配:多个终端同时运行
composer update,且都指向内部镜像 - 镜像服务未启用连接池:PDO 默认
PDO::ATTR_PERSISTENT => false,连接不复用
临时缓解:客户端侧降低并发压力
不改镜像服务也能快速止损,重点控制请求节奏和范围:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- CI 中显式串行化:在 GitHub Actions 的
strategy.matrix后加concurrency: 1,或用runs-on: self-hosted+ 单节点 runner - 禁用不必要的元数据加载:
composer install --no-dev --prefer-dist --no-suggest,跳过require-dev和suggest字段解析,减少 30%+ 请求量 - 强制使用本地锁文件:
composer install --ignore-platform-reqs(避免因 PHP 版本校验触发额外查询) - 预热镜像缓存:在 CI 前置步骤中先跑一次
curl -s https://your-mirror.com/packages.json > /dev/null,触发镜像服务预加载基础元数据
根治方案:镜像服务端连接池与限流配置
真正解决必须动服务端。以主流私有镜像方案为例:
-
Satis:升级至 v2.1.0+,启用
"cache": {"type": "redis"},把元数据读取从 MySQL 移到 Redis;若仍需 MySQL,修改config.php中 PDO DSN 加;charset=utf8mb4;options=1002,并设置PDO::ATTR_PERSISTENT => true -
Private Packagist:后台 →
Settings → Infrastructure → Database Connection Pool Size,调高至 ≥ 200;同时开启HTTP Cache TTL(建议 300s),让 CDN 缓存/p2/路径 -
Artifactory + Composer plugin:在
$JFROG_HOME/artifactory/var/etc/artifactory.system.properties中加artifactory.database.max.connections=250;并在system.yaml的composerblock 下启用cacheTtlSecs: 600 - 通用 MySQL 层:调高
max_connections(如设为 500),但更关键的是在镜像服务前加 Nginx,用limit_conn控制每 IP 并发数:limit_conn addr 10;
注意:所有服务端改动后,必须验证 show status like 'Threads_connected'; 是否稳定在阈值内,且 composer install 不再随机失败。最易被忽略的是——客户端未清理旧缓存,导致反复重试失败请求,持续加重 DB 压力。

















