db::master() 是链式连接器,仅对当次连续调用生效;断链(如分号、赋值)即失效,且事务中自动走主库无需使用,写操作或加锁查询也天然走主库。

Db::master() 不是开关,而是链式连接器——只对当次完整查询链生效,漏掉任意一环就失效。
Db::master() 为什么加了却没走主库?
常见错误现象:Db::master(); Db::table('user')->find() 依然走从库;Db::master()->table('user')->where('id', 1)->select() 中间断开链式调用(比如赋值给变量再调用)也会失效。
原因在于 Db::master() 返回的是一个**新实例**,它只影响后续紧跟的链式方法。一旦链路中断(如分号、变量赋值、中间插入其他 Db 调用),路由上下文就丢失了。
正确写法必须是一气呵成的连续链式调用:
Db::master()->table('user')->where('id', 1)->find()Db::master()->query('SELECT NOW()')Db::master()->name('user')->lock(true)->select()
注意:Db::master(true) 是 TP6.0+ 的可选参数,等价于 Db::master(),无需额外传参。
事务中还用不用 Db::master()?
完全不用。事务内所有操作(包括 select()、find()、value())自动强制走主库,这是框架硬规则,和是否加 master() 无关。
常见误操作:
- 在
Db::startTrans()后还加->master()—— 多余,且可能干扰连接复用 - 以为
Db::master()能“覆盖”事务行为 —— 实际上事务优先级更高,master()在事务中无意义
验证方式:开启 MySQL 的 SHOW PROCESSLIST,事务中的 SELECT 显示的 host 必定是主库地址。
哪些查询即使加了 master() 也无效?
不是所有“读操作”都能靠 master() 强制改道。以下情况会直接跳过读写分离逻辑,天然走主库,加不加都一样:
- 调用了写方法:
save()、insert()、update()、delete()、execute() - SQL 带锁:
FOR UPDATE或LOCK IN SHARE MODE(哪怕用query()执行) - 使用了
lock(true)方法
换句话说:Db::table('user')->lock(true)->find() 和 Db::master()->table('user')->lock(true)->find() 行为完全一致 —— 都走主库,后者只是冗余。
配置没启、read为空、deploy=0,master() 还管用吗?
管用,但仅限“当前查询”,且不依赖读写分离机制。
Db::master() 的底层逻辑是临时切换连接配置,它绕过了 rw_separate 路由判断,直接命中 write 配置节点。所以哪怕你没配 read、deploy 为 0,只要 write 配置存在且有效,master() 就能成功执行。
但要注意两个现实约束:
- 如果
write配置本身不存在或格式错误(比如写成数组而非关联数组),master()会抛出异常:Invalid write database config - 如果
write地址不可达,错误会直接暴露给业务层,没有 fallback 到从库的机制
真正容易被忽略的点是:很多人以为加了 master() 就万事大吉,却忘了检查 write 配置是否真实可用 —— 它不是“保证成功”,只是“保证往主库发”。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











