ThinkPHP 在 Swoole 协程环境下跑数据库,绝不是装个扩展、改个版本号就能搞定的事。问题的根源在于,ThinkPHP 默认的数据库连接机制(基于单例的 PDO 长连接)和 Swoole 的协程调度天生就“八字不合”。如果不做针对性调整,你会发现数据库连接要么被多个协程乱抢,要么直接报错,甚至引发事务状态污染。下面这几步,是必须踩实的硬功夫。

ThinkPHP 数据库配置文件 Swoole 协程适配【进阶】

database.php 必改三项硬配置

很多同学以为装个 think-swoole 扩展就万事大吉了,其实最关键的配置藏在 database.php 里。不改这三项,协程数据库永远走不通:

另外有一点经常被忽略:'hostname'、'username'、'password' 必须明文写死,不能依赖 getenv()$_ENV。因为协程上下文不保证环境变量始终可读,你线上调试时发现数据库连不上,多半就是这里出了问题。

禁止在初始化阶段执行数据库操作

协程还没启动就直接调 DB,你会看到一个经典的报错:SwooleCoroutineMySQL::query(): must be called in the coroutine。这个错误出现的位置往往很隐蔽——可能藏在模型的 __construct() 里,或者某个全局 Service Provider 的初始化方法中。

这个原则其实很简单:协程环境里的数据库操作,必须在协程上下文里执行,就像你进了游泳池才能游泳一样。

连接池不生效?检查调用方式是否正确

配置了连接池,但你发现 90% 的请求仍然走短连接?原因很简单:默认的 Db 门面类并没有走连接池逻辑。你得显式调用 Db::pool() 才能让连接池真正生效。

可以理解为:连接池就像是一个共享单车池,你默认骑的是自己的私车,得主动去扫码解锁才能用池里的车。

服务提供者中接管连接工厂

think-swoole 扩展不会自动替换 Db::connect() 的行为,你必须手动“劫持”连接创建逻辑。最简单的做法是在 app/provider.php 或自定义服务提供者中绑定:

use thinkswoolepoolDatabasePool;
use thinkswoolepoolChannelPool;
Container::getInstance()->bind('db', function ($app) {
    $config = $app->config->pull('database');
    return new DatabasePool($config, new ChannelPool(64));
});

DatabasePool 会按 SwooleCoroutine::getuid() 分配隔离连接,确保每个协程独占连接,避免事务、fetch 模式等状态污染。这一步是很多教程里没讲透的,但恰恰是生产环境稳定运行的关键。

本文转载于:https://www.php.cn/faq/2824301.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。