要让ThinkPHP 6.0项目真正跑通数据库并扛住高并发流量,必须同时完成三件事:在database.php中正确声明多库连接、按环境分离敏感参数、在Swoole模式下启用协程连接池——漏掉任意一环,都会在压测时突然爆出Too many connections或Connection refused。

在config/database.php中预定义多个数据库连接
第一步:打开config/database.php文件,找到'connections' => []这一行,在花括号内新增连接配置块。
第二步:为每个库起一个全小写+下划线的键名,例如'order_db'和'log_db';【键名严禁含大写字母、点号或空格】,否则Db::connect()会直接抛出Connection not found异常。
第三步:每个键名下必须完整填写'type'、'hostname'、'database'、'username'、'password'五项,缺一不可;其中'type'只能是mysql、pgsql等官方驱动名,传mysqli或pdo_mysql会导致Class 'PDO' not found致命错误。
第四步:保存文件后,立刻执行php think clear:config命令——这一步跳过就等于没配,新连接永远不会被框架识别。
立即学习“PHP免费学习笔记(深入)”;
用.env分离开发与生产环境的数据库参数
方法一:在项目根目录新建UTF-8无BOM的.env文件,写入两组配置:
[DATABASE_MASTER]<br>TYPE=mysql<br>HOSTNAME=192.168.1.100<br>DATABASE=prod_main<br>USERNAME=app_rw<br>PASSWORD=xxx
[DATABASE_SLAVE]<br>TYPE=mysql<br>HOSTNAME=192.168.1.101<br>DATABASE=prod_read<br>USERNAME=app_ro<br>PASSWORD=yyy
方法二:修改config/database.php中对应连接的参数,全部改用env()函数读取,例如:'hostname' => env('database_slave.hostname', '127.0.0.1')。注意:env()第二个参数只是本地调试兜底值,线上必须由.env提供真实凭据。
在Swoole环境下启用协程数据库连接池
① 确保已安装topthink/think-swoole >= 3.1.0且Swoole >= 4.8.0;FPM模式下该配置完全无效,只在Swoole Worker进程生效。
② 打开config/swoole.php,在'pool' => []内添加db配置:
'db' => [<br> 'enable' => true,<br> 'max_active' => 20,<br> 'max_wait_time' => 3,<br> 'idle_timeout' => 300,<br>],
③ 关键点:max_active是硬上限,不是并发数,而是连接总数;设为20表示最多允许20条连接同时存在,超过则排队等待;max_wait_time设太小(如100ms)会导致大量PoolTimeoutException,设太大(如5000ms)会让请求卡死拖垮接口。
④ 启动服务后,所有Db::table()调用自动走池子——但注意:模型类(如UserModel)默认不走池子,必须手动重写db()方法返回Db::pool()实例。
针对PolarDB等云数据库的特殊配置
在config/database.php对应连接块中,必须显式关闭三项默认行为:
'break_reconnect' => false, — PolarDB不支持频繁断线重连,开启反而触发更多失败重试;
'persistent' => false, — PHP-FPM下持久连接不可靠,协程模式下更会引发连接泄漏;
'deploy' => 0, — 禁用多服务器部署逻辑,避免路由开销(PolarDB是单endpoint);
同时确保'charset' => 'utf8mb4',否则中文插入会报Incorrect string value。
运行时动态切换数据库连接
方法一:在控制器中调用$db = Db::connect('log_db');,后续所有->table()、->where()、->select()都绑定该连接;推荐显式持有实例,避免链式中断。
方法二:在模型类顶部声明protected $connection = 'log_db';,该模型所有find()、save()操作自动走指定库;注意事务不跨连接,Db::connect('a')->startTrans()和Db::connect('b')->startTrans()完全隔离。
方法三:临时查从库或跨库校验时,直接传键名调用Db::connect('slave_db')->table('user')->select();若报Connection not found,立即检查键名拼写、大小写、是否漏写进connections数组。



















