跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

ThinkPHP读写分离怎么设_ThinkPHP模型读写配置介绍【方法】

ThinkPHP 6 读写分离需同时满足 deploy => 1、rw_separate => true,且 read 必须为数组套数组、write 为单数组,否则默认全走主库;查询带锁、在事务中或调用 ->master() 时强制走主库。 ThinkPHP 6 的读写分离不是“配了 read 就自动走从库”,必须同时满足
deploy => 1
、
rw_separate => true
,且
read
和
write
配置结构正确,否则全走
default
连接——也就是主库。 database. php 里怎么写才算真正启用读写分离 很多人把
read
写成单个数组(比如
['hostname' => '192.168.1.10']
),结果 TP 启动就报错或静默失效。TP6 要求
read
必须是「数组套数组」,哪怕只配一个从库也要写成
[0 => ['hostname' => '192.168.1.10']]
;
write
只能是单个完整连接数组,不能是数组套数组,否则直接抛出
Invalid write database config
。 关键点在于:整个读写分离逻辑由
connections.mysql
下的配置驱动,而
default
只是用来指向这个配置名:
default
设为
'mysql'
(字符串)
connections.mysql
下必须包含:
'deploy' => 1
、
'rw_separate' => true
、
'read' => [[...]]
、
'write' => [...]
漏掉
deploy => 1
,整个读写分离模块根本不会初始化 为什么 Db::name('user')->select() 还是走主库 TP6 不是按 SQL 类型(如是否含 SELECT)判断路由,而是按方法语义 + 上下文联合判定。以下情况会强制走主库: 立即学习 “ PHP免费学习笔记(深入) ”; 查询带锁:
->lock(true)
或原生 SQL 含
FOR UPDATE
/
LOCK IN SHARE MODE
当前处于事务中:
Db::startTrans()
后的所有查询,无论是否只读,全部回落到主库 调用了写操作连贯方法(如
->order()->limit()->count()
),TP 有时会误判为写意图 纯读方法(
find()
、
select()
、
value()
、
column()
)才可能进从库,前提是没触发上述任一条件。 PHP 8.5.5 PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。 下载 Db::connect() 和 Db::name() 对读写分离的影响
Db::name('user')
完全依赖
default
所指向的连接配置(即
connections.mysql
)是否开启
rw_separate
;而
Db::connect('xxx')
是创建全新连接实例,它只认自己配置里的
hostname
,完全不参与
read
/
write
路由逻辑。 也就是说: 想用读写分离 → 必须走
Db::name()
(或
Db::table()
)+ 正确的
connections.mysql
配置 用了
Db::connect('slave1')
→ 等于手动绕过读写分离机制,该连接永远只连指定地址 临时切从库又不想改全局?只能通过
Db::$connection->config(['read' => [...]])
动态重设,没有
->slave()
这种链式方法 从库延迟时业务层怎么兜底 TP6 不做延迟探测、不自动故障转移、不支持权重轮询——它只是随机选一个
read
数组元素去连。一旦从库同步滞后,
save()
后立刻
find()
可能查不到数据,这是框架明确声明的「需业务层兜底」场景。 常见应对方式: 强一致性读:对刚写入就查的场景,显式加
->master()
,例如
Db::name('user')->master()->where('id', $id)->find()
缓存兜底:写后更新 Redis 缓存,读优先走缓存,避免直击从库 延迟容忍提示:前端展示「数据同步中」状态,配合定时轮询 别指望 TP 自动识别主从延迟并切换连接——它连
SHOW SLAVE STATUS
都不执行。

相关文章