thinkphp多数据库配置与读写分离本质不同:前者指不同业务库(如user_db、log_db),后者是同一逻辑库的主从路由(如myapp库的master/slave);tp6要求read必须为二维数组、write为一维数组,且deploy=1与rw_separate=true缺一不可。

ThinkPHP 多数据库配置和读写分离不是一回事——多库是不同业务库(如user_db、log_db),读写分离是同一逻辑库的主从节点路由(如myapp库的master和slave1)。混淆这两者,配置必翻车。
TP6 的 read/write 配置必须套两层数组
TP6 要求 read 必须是「数组套数组」,哪怕只配一个从库,也得写成 [['host' => '192.168.1.11']];写成 ['host' => '192.168.1.11'] 会直接报错 Call to a member function query() on null。
-
write只能是单个关联数组,不能是数组套数组,否则启动就抛Invalid write database config -
read和write必须同级放在connections.mysql下,且deploy => 1和rw_separate => true缺一不可 - 所有节点的
database值必须一致,否则跨表 JOIN 或事务会出错 - 从库配置里别写
prefix或deploy,这些字段只对主连接生效,写了也忽略
TP6 的 SELECT 不自动走从库,必须显式声明
Db::table('user')->select() 默认仍走主库,除非你加了 ->useReadConnection() 或满足特定条件。框架不会解析 SQL 类型来自动分流。
- 纯读方法(
find()、value()、column())在rw_separate === true且非事务中时,才尝试走read - 一旦调用过
->lock(true)、->master()或处于事务内(Db::transaction()),后续所有查询强制回主库 -
Db::connect('mysql_slave')这类自定义连接名完全绕过读写分离逻辑,它只认自己配置里的hostname - 想临时强制走主库查刚写入的数据?必须加
->master(true),别指望“写完自动同步”
TP5 的 read_master 开关极易被上下文覆盖
TP5 不靠 read/write 数组,而是依赖 read_master => true + 单个 slave 配置,但它的路由逻辑非常脆弱。
- 上一条执行的是
INSERT/UPDATE/DELETE,下一条select()就会被跳过从库,静默走主 - 事务中
inTransaction() === true,所有查询一律不走从库 -
slave必须是单层关联数组(如['host' => '192.168.1.10']),不能是二维,也不能写成字符串 - 环境变量无法覆盖
read_master,必须在database.php的连接配置里硬写键值对
DB_DEPLOY_TYPE=1 是旧版兼容方案,但限制极多
TP3.2–TP5.x 支持用 DB_DEPLOY_TYPE => 1 + DB_HOST 拼接 IP 的方式,看似简单,实则埋坑。
-
DB_HOST必须是英文逗号分隔,如'192.168.0.1,192.168.0.2',首个为默认主库 -
DB_USER和DB_PWD若需不同账号,必须也用逗号拼接,顺序要严格对应DB_HOST - 不支持从库权重、故障转移或延迟检测,挂一个从库,轮询就会失败
-
.env文件无法定义这种结构化配置,只能覆盖扁平变量,所以DB_HOST不能拆成多个环境变量
最常被忽略的一点:所有从库的 charset 必须和主库完全一致,尤其是 utf8mb4 vs utf8。emoji 字段写入失败、中文乱码,八成是这里没对齐。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











