ThinkPHP 6.0 实现数据库读写分离需启用 deploy=1 和 rw_separate=true 两个开关,并在 connections.mysql 下配置 write(单数组)和 read(二维数组),主从 database 名须一致,纯 SELECT 自动走从库,事务/锁/写操作强制走主库。

ThinkPHP 6.0 配置数据库读写分离,核心不是“多写几个 host”,而是启用部署模式 + 明确主从结构 + 正确组织配置层级。配错一个键或位置,读写分离就完全不生效。
必须开启的两个开关
这两个配置缺一不可,且必须放在具体数据库连接配置内部(比如 connections.mysql 下),不能写在顶层 default 或全局配置里:
- 'deploy' => 1:这是读写分离的总闸门。不设它,哪怕你写了 read/write,TP6 也全走默认连接(通常是主库);
- 'rw_separate' => true:表示启用读写自动分离策略。设为 false 时,所有操作都走 write,除非手动调用 ->master() 或 ->slave()。
主库和从库怎么写才合法
主从配置必须按框架约定格式书写,否则会报错或静默失效:
- write 只能是单个数组,包含完整连接参数(hostname、username、password、database、charset 等)。写成数组套数组会直接报错 “Invalid write database config”;
-
read 必须是二维数组(即数组套数组),哪怕只配一个从库也要写成
[ ['host' => '192.168.1.11'] ]。写成一维(如['host' => '...'])会导致Call to a member function query() on null; - 所有节点(主+从)的 database 名必须一致,否则跨库 JOIN、事务或模型关联会出问题;
- 从库账号需有只读权限(如
ro_user),主库账号需有读写权限。
哪些操作会自动走从库?哪些一定走主库?
TP6 不是“所有 SELECT 都走从库”,而是按语义和上下文智能判断:
- ✅ 自动走从库:纯读操作,如
Db::table('user')->select()、->find()、->value()、->column(); - ❌ 强制走主库(无法绕过):
• 在事务中执行的任何查询(Db::transaction()内所有 select/find 都走主库);
• 带行锁的查询(->lock(true)、->forUpdate()、原生 SQL 含FOR UPDATE);
• 所有写操作(insert()、update()、delete()、save());
• 显式调用->master(true)。
常见踩坑与验证方法
配完别急着测试业务,先确认基础是否跑通:
- 用
Db::getLastSql()查看生成的 SQL 和实际执行的连接; - 在非事务、非锁场景下执行
Db::table('user')->select(),观察日志或数据库慢查记录,确认是否命中从库 IP; - 如果始终走主库,检查是否漏了
'deploy'=>1,或read写成了一维数组; - 不要用
Db::connect('slave')来模拟读写分离——那是独立连接,不参与 TP6 的路由逻辑; - 主从延迟无法靠配置解决,业务上“写后立刻读”必须进事务,或加缓存兜底。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











