webman需自行构建mysql连接池,因不内置且禁用pdo持久连接;推荐用swoole\connectionpool+coroutine\mysql实现并发复用,配合适当mysql服务端参数调优。

Webman 本身不内置 MySQL 连接池,但作为基于 Workerman 的常驻内存框架,它天然支持协程和长生命周期连接管理——这意味着你**必须自己构建或集成连接池**,否则每次请求都 new PDO 或 mysqli,会快速耗尽 MySQL 连接数,且无法复用。
Webman 中不能直接用 PDO::ATTR_PERSISTENT
在 Webman(或任何 Workerman/Swoole 常驻进程)中启用 PDO::ATTR_PERSISTENT => true 是危险的:持久连接由 PHP 进程维护,而 Webman 的 Worker 进程长期运行,多个协程可能并发复用同一个连接,导致事务残留、临时表冲突、会话变量污染,甚至查询结果错乱。
常见错误现象包括:
- 某次请求开启事务后未提交/回滚,下次请求复用该连接时发现
ERROR 1305 (42000): SAVEPOINT does not exist -
SELECT @@session.sql_mode返回值异常,或USE temp_db影响后续请求 - 连接数持续上涨,
SHOW STATUS LIKE 'Threads_connected'显示远超预期
所以,不要在 Webman 中依赖 PDO 持久连接。它不是连接池,只是“连接不关”,在长生命周期下反而制造问题。
用 Swoole\Coroutine\MySQL + ConnectionPool 实现真连接池
Webman 兼容 Swoole 协程扩展(需已安装并启用 swoole 扩展),这是目前最稳定、性能最好的方案。核心是使用 Swoole\ConnectionPool 管理 Swoole\Coroutine\MySQL 实例。
实操建议:
- 定义连接池类,例如
app/pool/MySqlConnectionPool.php,构造时传入创建连接的闭包 - 池大小按并发预估:一般设为
min(20, max_connections * 0.6),避免打爆 MySQL - 务必设置
$pool->get()超时(如 100ms),防止协程卡死在获取连接上 - 使用后必须调用
$pool->put($conn)归还,推荐用try/finally或 defer 保证执行
简短示例:
use Swoole\ConnectionPool;
use Swoole\Coroutine\MySQL;
<p>$pool = new ConnectionPool(function () {
$mysql = new MySQL();
$mysql->connect([
'host' => '127.0.0.1',
'port' => 3306,
'user' => $_ENV['DB_USER'],
'password' => $_ENV['DB_PASS'],
'database' => $_ENV['DB_NAME'],
'charset' => 'utf8mb4',
]);
return $mysql;
}, 20); // 最大20个连接</p><p>// 在协程中使用
$conn = $pool->get(100); // 100ms 超时
if (!$conn) throw new RuntimeException('MySQL pool timeout');
try {
$result = $conn->query('SELECT id FROM users LIMIT 1');
} finally {
$pool->put($conn); // 必须归还
}
</p>
Workerman-DB-Connection 不适合 Webman 高并发场景
社区有 workerman/db-connection 这类基于连接复用的库,但它本质是“单连接+队列排队”,所有请求串行等待同一个连接,吞吐量极低。在 Webman 中启用后,QPS 可能比不用还差。
如果你看到文档说“Workerman 支持数据库连接池”,大概率混淆了概念——它只提供连接复用(reuse),不是连接池(pool)。真正需要的是并发可扩展的连接供给能力。
关键差异:
-
workerman/db-connection:1 个连接 + 1 个 FIFO 队列 → 请求排队等,延迟高 -
Swoole\ConnectionPool:N 个独立连接 + 协程并发获取 → 请求并行执行,延迟低
别被名字误导。检查源码里有没有 new MySQL() 多次调用,有没有 Channel 或 Pool 类封装,才是判断真假连接池的关键。
MySQL 服务端参数必须同步调优
光配好 Webman 端没用。若 MySQL 的 max_connections 还是默认 151,或 wait_timeout 设成 28800(8 小时),连接池里的空闲连接很快会被 MySQL 主动断开,下次取出时直接报 MySQL server has gone away。
必须调整的 MySQL 参数:
-
max_connections = 500(根据服务器内存和并发预估) -
wait_timeout = 600(10 分钟,与连接池idleTimeout匹配) interactive_timeout = 600-
max_connect_errors = 100(防暴力探测干扰)
改完记得 sudo systemctl restart mysql 并验证:mysql -e "SHOW VARIABLES LIKE 'max_connections';"
最容易被忽略的一点:连接池的“最大连接数”和“空闲超时”必须与 MySQL 的 wait_timeout 严格对齐。差几秒都可能导致连接被服务端静默关闭,而客户端仍认为它可用——这种状态不一致,只能靠心跳检测或连接使用前 ping 来缓解,但会增加额外开销。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











