必须同时满足四个硬性条件:①deploy=>1为整型数字;②rw_separate=>true置于connections['mysql']内;③write为单维、read为二维数组(或改用slave键);④通过SQL日志验证READ/SLAVE标识。

要在ThinkPHP 6.0中让SELECT类查询自动分发到从库、INSERT/UPDATE等写操作固定走主库,必须同时满足四个硬性条件,漏掉任意一个都会导致所有查询静默回落主库,且不报错、不提示、不日志警告。
配置 deploy 和 rw_separate 开关
这一步是启动读写分离机制的总闸门,不是可选项——【deploy => 1 必须是整型数字,写成 '1' 或 true 都无效】。
第一步:打开 config/database.php 文件,定位到 connections['mysql'](或你实际使用的连接名)配置块内。
第二步:确认该块中存在且仅存在以下两行,不能放在顶层、不能放在 default 键下、不能写在其他连接配置里:
立即学习“PHP免费学习笔记(深入)”;
'deploy' => 1,
'rw_separate' => true,
第三步:删除 connections 外层或 default 下同名键值,否则开关不起作用。
定义 write 主库与 read 从库结构
TP6 对数组维度极其敏感,结构错一点就静默失效,而不是报错中断。
方法一:标准二维 read + 单维 write(推荐)
'write' => [
'hostname' => '192.168.1.10',
'database' => 'myapp',
'username' => 'root',
'password' => '123456',
'charset' => 'utf8mb4'
],
'read' => [
[
'hostname' => '192.168.1.11',
'database' => 'myapp',
'username' => 'slave_ro',
'password' => 'ro_pwd',
'charset' => 'utf8mb4'
],
[
'hostname' => '192.168.1.12',
'database' => 'myapp',
'username' => 'slave_ro',
'password' => 'ro_pwd',
'charset' => 'utf8mb4'
]
],
注意:read 必须是二维数组,哪怕只有一个从库也要套一层方括号;write 只能是单维关联数组,写成 [['hostname' => ...]] 会直接抛 Invalid write database config 异常。
方法二:使用 slave 键替代 read(TP6.3+ 兼容写法)
某些 TP6.x 小版本对 read/write 键支持不稳定,可改用官方文档认可的 slave 键:
'slave' => [
[
'hostname' => '192.168.1.11',
'database' => 'myapp',
'username' => 'slave_ro',
'password' => 'ro_pwd'
],
[
'hostname' => '192.168.1.12',
'database' => 'myapp',
'username' => 'slave_ro',
'password' => 'ro_pwd'
]
],
此时仍需保留 'deploy' => 1 和 'rw_separate' => true,但不再需要 write 和 read 键。
验证是否真正走从库
别信配置文件写得漂亮,要靠真实 SQL 日志确认路由结果。
第一步:在 config/database.php 中开启调试模式:
'debug' => true,
第二步:在控制器中执行纯读操作:
Db::name('user')->select();
第三步:查看 runtime/log 下最新日志文件,搜索关键词「READ」或「SLAVE」,若看到类似「Use slave connection: 192.168.1.11」即表示成功;若只看到「Use master connection」或无任何连接地址输出,则说明配置未生效。
第四步:强制触发主库回退场景验证健壮性:
Db::startTrans();
Db::name('user')->where('id', 1)->find();
Db::commit();
此时日志中必须出现「Use master connection」——这是正确行为,证明事务内强制走主库逻辑已激活。



















