ThinkPHP 8.1 读写分离需同时启用 'deploy' => 1 和 'rw_separate' => true 开关,write 必须为单数组主库配置,read 必须为二维数组(即使单从库),select/find 等默认走从库,但带锁、事务内或强一致性读需手动调用 ->master() 或异常 fallback。

ThinkPHP 8.1 的读写分离不是“自动识别 SQL 类型”就能生效的,而是依赖明确的配置开关、连接结构和调用方式。配置错一个键,或漏掉一个开关,读操作就会默默打到主库,从库完全闲置。
核心配置必须启用两个开关
在 config/database.php 中,`connections.mysql` 下必须同时设置:
- 'deploy' => 1:开启分布式部署总开关,没有它,整个读写分离逻辑不触发
- 'rw_separate' => true:启用读写自动分离策略,设为 false 则所有操作都走主库
仅写 read 和 write 数组但没开这两个,TP8.1 会直接忽略从库配置。
主从连接结构要严格符合格式
TP8.1 要求:
立即学习“PHP免费学习笔记(深入)”;
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
-
write 必须是单数组(只允许一个主库),包含完整参数:
hostname、username、password、database、charset等 -
read 必须是「数组套数组」,哪怕只有一个从库也要写成:
[0 => ['hostname' => 'slave1', 'username' => 'r1', ...]] - 所有节点的
database名必须一致,否则跨库 JOIN 或事务会失败
错误示例:'read' => ['hostname' => 'slave1'] 会导致 Call to a member function query() on null。
哪些操作真正走从库?
TP8.1 不是“所有 SELECT 都走从库”,而是按方法语义和上下文判断:
- 显式读方法如
select()、find()、value()、column()→ 默认走从库 - 带锁查询(
lock(true)或 SQL 含FOR UPDATE)→ 强制走主库 - 事务中任何查询(含纯
SELECT)→ 全部回落主库 - 连贯操作中含
order()+limit()+count()组合 → 可能误判,建议拆步或加->useReadConnection()
手动控制与异常兜底
业务强一致性场景需主动干预:
- 写后即读(如注册完立刻查用户):用
Db::master()->table('user')->find(1)强制走主库 - 从库故障时不会自动切主:需捕获
PDOException,手动 fallback 到主库重试 - 自定义连接(如
Db::connect('report_db'))会绕过读写分离逻辑,应避免
多个从库采用轮询策略,无延迟探测或自动下线,运维需配合心跳监控。


















