ThinkPHP 5.1 默认不内置主从读写分离逻辑,需手动配置;刚写完立即查不到是因读请求路由到未同步的从库,应通过 Db::master(true) 或显式 connect('write') 强制关键读走主库,并结合 GTID/心跳表检测延迟。

ThinkPHP 5.1 默认不内置主从读写分离逻辑,需手动配置或借助扩展实现。一旦配置了主从(比如一主多从),又没处理延迟问题,就容易出现“刚写完马上查不到”——本质是读请求打到了还没同步完的从库上。
明确读写分离路由规则
TP5.1 的数据库配置支持 read 和 write 分离,但默认不会自动识别“刚写过的数据该读哪”。必须结合业务上下文做显式控制:
- 用户提交订单后,紧接着查该订单详情,应强制走主库:用
Db::connect('write')->table('order')->where('id', $id)->find() - 历史订单列表、商品搜索等非强一致场景,才走从库(如
Db::connect('read')->...) - 避免全局设置
'read_master' => true后就不管了——它只在读失败时降级,不解决“读旧数据”问题
对关键操作加主库读标记
TP5.1 支持临时切换连接,适合写后立即读的链路:
- 在事务提交后,用
Db::master(true)强制下一条查询走主库(注意:该标记仅对当前请求有效) - 封装一个工具方法,例如
OrderService::getByIdAfterWrite($id),内部统一走主库查询 - 不要依赖“等几秒再查”,延迟不可控,且影响用户体验
用 GTID 或心跳表验证从库真实延迟
Seconds_Behind_Master = 0 不代表数据已就绪。TP5.1 本身不提供延迟检测,需自行集成:
- 建一张
heartbeat表,主库每秒写入NOW(6);从库查该值与本地时间差,>500ms 就跳过该从库 - 若开启 GTID,可通过
SELECT @@global.gtid_executed;对比主从 GTID 集合,差集即未应用事务 - 把延迟检查逻辑放在数据库连接池初始化或读库选择前,避免把请求路由到高延迟节点
拆大事务 + 避免从库过载
很多延迟不是网络导致,而是从库被拖慢:
- TP5.1 批量插入时,别用
addAll()一次性塞 10 万条;改用分批(如每次 500 条 +commit()) - 报表类慢查询、
GROUP BY大表统计,不要跑在从库上——单独部署只读分析库,或改用异步导出 - 检查从库
innodb_buffer_pool_size是否明显小于主库,SSD 磁盘是否被其他进程抢占 IO

















