Workerman 4 中不能全局共享 MySQL 连接,因多进程 fork 后会继承同一 socket 导致读写错乱、中断或段错误;必须在 onWorkerStart 中为每个子进程单独创建长连接,并推荐使用 Workerman\MySQL\Connection 配合心跳检测与轻量连接池复用。

为什么不能全局共享一个 MySQL 连接
WorkerMan 启动后会 fork 多个子进程(默认 4 个),每个子进程独立运行。如果在主进程或全局作用域中初始化一个 MySQL 连接,所有子进程会继承该连接的文件描述符,导致多个进程同时读写同一个 socket,出现数据错乱、连接中断甚至段错误。这不是“连接没复用”,而是“连接被误共享”。
onWorkerStart 中为每个进程创建独立连接
这是最基础也最稳妥的做法:每个子进程启动时,单独建立自己的长连接,并保持活跃。
- 连接必须在 onWorkerStart 回调里创建,确保属于当前子进程上下文
- 推荐使用 Workerman\MySQL\Connection(官方维护,支持异步查询回调)
- 避免在 onMessage 或 onConnect 中新建连接,否则每次请求都重连,失去复用意义
- 可配合心跳 SQL(如
SELECT 1)定期探测连接有效性,失败时重建
引入轻量级连接池管理复用逻辑
单连接虽稳定,但高并发下可能成为瓶颈。可用简单队列 + 异步回调模拟连接池行为:
- 在 onWorkerStart 中预创建 N 个 Workerman\MySQL\Connection 实例,存入数组或 SplQueue
- 每次需要查询时,从队列取一个空闲连接,标记为“忙”,执行 query 并传入回调
- 回调执行完毕后,把连接放回队列,恢复为“空闲”状态
- 连接异常时主动 close 并丢弃,不归还;下次取用自动 fallback 到新连接
注意:这个池是进程内单例,无需跨进程同步,也不依赖锁或共享内存,天然适配 WorkerMan 的多进程模型。
用 Redis 或消息队列解耦耗时 DB 操作
对于写多读少、事务复杂或含慢查询的场景,硬扛异步 MySQL 并非最优解。更推荐:
- 业务层将写操作序列化为任务,推送到 Redis List / Kafka / RabbitMQ
- 另起一个专用 Worker 进程消费队列,用同步方式执行 MySQL 操作(此时可放心用 PDO 或 mysqli,无阻塞风险)
- 通过 ACK、重试、死信队列保障可靠性,比在异步回调里拼事务更可控
这本质上是把“数据库连接复用”问题,转为“任务生命周期管理”问题,反而更贴合 WorkerMan 的设计哲学。


















