thinkphp6读写分离必须同时满足deploy=>1、rw_separate=>true、read为二维数组、write为单维数组四条件;缺一则全部查询静默走主库,且db::name()依赖配置而db::connect()绕过分离机制。

ThinkPHP 的读写分离不是“配完就能用”,它必须同时满足 deploy => 1、rw_separate => true、read 是二维数组、write 是单维数组这四个硬性条件,缺一不可——漏掉任意一个,所有查询都会静默回落到主库。
database.php 中 connections.mysql 的配置结构必须严格按 TP6 要求写
很多人把 read 写成一维数组(比如 'read' => ['hostname' => '192.168.1.11']),结果框架启动不报错但读操作永远走主库。TP6 明确要求:read 必须是二维数组,哪怕只有一个从库也要写成 'read' => [['hostname' => '192.168.1.11']];write 只能是单维数组,写成二维会直接抛出 Invalid write database config。
关键配置项必须同级存在:
-
'deploy' => 1:总开关,没有它整个读写分离模块根本不初始化 -
'rw_separate' => true:仅当deploy === 1时才生效 -
'write'必须含完整连接参数(hostname、username、password、database等),少一个可能连不上或连错库 -
'read'中每个子数组也必须包含完整参数,不能只写hostname—— 否则报Database config read_config is invalid - 所有节点的
database名必须一致,否则跨库 JOIN 或事务会出问题
Db::name() 和 Db::connect() 对读写分离的影响完全不同
Db::name('user')->select() 是否走从库,完全取决于 default 指向的那个连接(如 'mysql')是否正确启用了 rw_separate;而 Db::connect('log_db') 创建的是独立连接实例,它只认自己配置里的 hostname,完全不参与 read/write 路由逻辑。
常见误用场景:
- 以为
Db::connect('slave1')就能实现读写分离 → 实际上等于手动绕过机制,该连接永远只连指定地址 - 在模型里调用
$this->db()->master()后忘了重置 → 后续所有查询锁定主库 - 用
Db::query('SELECT ...')却没加->useReadConnection()→ 默认走主库(TP6 不自动识别 SQL 类型)
哪些操作会被强制发往主库?
TP6 不解析 SQL 语义,而是靠方法名和上下文做路由判断。以下情况一律走 write 连接:
- 调用
insert()、update()、delete()、save()、execute()等明确写意图的方法 - 查询中带锁:
->lock(true)或原生 SQL 含FOR UPDATE/LOCK IN SHARE MODE - 当前处于事务中:
Db::startTrans()后的所有查询,包括纯select(),全部回落主库 - 连贯操作中混用
order()+limit()+count(),TP 有时会误判为写意图
注意:Db::name('user')->master(true)->find() 是显式切主库的合法方式,但 ->slave(true) 并不存在 —— 框架没有提供反向强制走从库的链式方法。
从库延迟、宕机、字符集不一致这些实际问题怎么应对
TP6 不做延迟检测、不支持自动故障转移、不感知从库健康状态。你写的 read 数组顺序就是轮询顺序,某台从库宕机只会触发连接超时然后跳到下一个,不会标记下线,下次轮到还会再试一次。
真实业务中必须自己兜底:
- 「写后立刻读」场景(如注册后查用户信息)必须加
->master(true),否则大概率查不到 - 所有从库的
charset必须与主库一致(推荐统一为utf8mb4),否则 emoji 字段写入失败或乱码 - Redis 缓存了旧 schema(如
schema_cache_type = redis)时,改完配置必须清缓存,否则仍按旧连接初始化 - 需要权重轮询?得设
'readwrite_type' => 'balance'并在每个read子数组里加'weight' => 3;但权重不能运行时调整,改完得 reload 配置
最常被忽略的一点:TP6 的读写分离是「连接层路由」,不是「SQL 层代理」。它不修改你的 SQL,也不拦截执行,只是在构造查询对象时决定用哪个连接实例 —— 所以一切控制权都在配置和调用方式上,没有中间件或全局钩子能帮你自动补救。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











