ThinkPHP 6/8 读写分离需同时满足 deploy=1、rw_separate=true 及 read/write 正确数组结构三要素,且必须置于 connections['mysql'] 内;TP5 则依赖 read_master 与非事务上下文。

ThinkPHP 6/8 的读写分离不是“配了 read 就自动走从库”,必须同时满足 deploy、rw_separate、read/write 结构三要素,缺一不可;TP5 则依赖 read_master + 非事务上下文,逻辑完全不同。
TP6 必须在 connections.mysql 内启用 deploy 和 rw_separate
这两个开关必须写在具体连接配置内部,比如 connections['mysql'] 里,写在顶层 default 或全局位置完全无效。TP6 不会因为存在多个数据库地址就自动触发分离——它只认这两个布尔标记。
-
'deploy' => 1是分布式模式总开关,漏掉它整个读写分离逻辑不初始化 -
'rw_separate' => true表示启用自动路由,设为false时所有操作都走主库,除非手动调用->master()或->slave() - 如果把它们写在
default下或connections外层,Db::name('user')->select()仍会默默走主库,且无任何报错提示
TP6 的 read 必须是二维数组,write 只能是单数组
TP6 强制要求 read 是数组套数组结构(哪怕只有一个从库),write 必须是单个完整配置数组。写错格式会导致连接对象为 null,报错 Call to a member function query() on null。
- 正确写法:
'read' => [['hostname' => '192.168.1.11', 'database' => 'myapp', ...]] - 错误写法:
'read' => ['hostname' => '192.168.1.11'](一维,TP6 解析失败) -
'write'若写成数组(如['host' => 'm1'], ['host' => 'm2']),启动直接抛出Invalid write database config - 所有节点的
database名必须一致,否则跨库 JOIN 或事务会出错
TP8 用 Env 动态控制灰度开关,但 rw_separate 必须 filter_var 转布尔
TP8 支持通过 .env 控制读写分离是否启用,但不能直接把字符串 'true' 当布尔用——框架内部用 === true 判断,Env::get('DB_RW_SEPARATE') 返回的是字符串,结果恒为 false。
立即学习“PHP免费学习笔记(深入)”;
-
.env中写:DB_DEPLOY=1和DB_RW_SEPARATE=true -
config/database.php中必须写:'rw_separate' => filter_var(Env::get('DB_RW_SEPARATE', 'false'), FILTER_VALIDATE_BOOLEAN) -
'deploy' => (int)Env::get('DB_DEPLOY', 0)要放在connections['mysql']内部,不能放外面 - 灰度阶段若需按用户 ID 分流,必须用
Db::event('before_select')拦截,并调用useReadConnection(true),Env 本身不支持请求级条件
TP5 的 read_master 依赖非事务 + 上一条非写操作
TP5.0–5.1 的读库路由极简:只检查是否在事务中、上一条 SQL 是否为写操作(靠内部 lastSql 标记)。哪怕你配了从库,只要刚执行过 insert(),接下来的 find() 就一定走主库,且无日志、无提示。
-
read_master => true必须在连接配置里显式写,.env值要通过env('READ_MASTER', false)读取,否则不生效 -
slave配置必须是一维扁平化(如'hostname' => 's1,s2'),写成二维数组会静默失败 - 事务中所有查询强制走主库,这是硬编码逻辑,无法绕过
-
query()、execute()、关联查询默认不走从库,只有find()、select()、value()等明确语义的读方法才参与路由
最易被忽略的是:TP6/8 的 read 配置一旦生效,事务内所有查询都会自动回落主库——这不是 bug,是为保证一致性做的强制策略;而 TP5 的 fallback 条件更隐蔽,全靠内部状态标记,调试时几乎看不到依据。配置写完务必用 Db::getLastSql() 和实际数据库连接日志交叉验证,别只信代码结构。



















