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

ThinkPHP中DbConnect_读写分离与主库强制读配置【操作】

ThinkPHP6读写分离需同时满足'deploy'=>1、'rw_separate'=>true、'read'为非空数组三条件;Db::connect()指定独立连接不参与分离路由,Db::name()则依赖default配置;强制主库读须用Db::master()->table()->find()链式调用或置于事务中。 ThinkPHP 的读写分离不是“配了就能用”,而是依赖明确的配置开关和调用方式。主库强制读也不是加个方法就生效,关键在作用范围和链式调用是否延续。 读写分离必须显式启用 仅在 database. php 里写上多个数据库地址或 'read' 数组,不会自动触发分离。TP6 要求同时满足三个条件: 'deploy' => 1 :开启多服务器部署模式,这是总闸门 'rw_separate' => true :启用读写自动分离逻辑 'read' 配置非空且为数组 :例如
'read' => [['host' => '192.168.1.10']]
,不能是
[]
null
或对象 缺一不可。漏掉
'deploy' => 1
,整个读写分离模块根本不会初始化。 Db::connect() 与默认连接的区别
Db::connect('mysql')
是显式指定一个已命名的连接配置(需在 database.php 的 connections 下定义),它独立于全局默认行为,不参与读写分离路由判断。 立即学习 “ PHP免费学习笔记(深入) ”;
Db::name('user')
Db::table('user')
则始终走
default
所指向的连接配置,是否走从库,完全取决于该配置中
'rw_separate'
是否开启、
'read'
是否有效。 常见误区:以为
Db::connect('slave_read')
后再调用
->table('user')->select()
就能复用该连接——其实不行,
->table()
会重新绑定默认连接,必须写成
Db::connect('slave_read')->table('user')->select()
。 强制主库读的两种可靠方式 不是所有“想读主库”的场景都适合同一种写法,得看上下文: 单次查询强一致 :用
Db::master()->table('user')->where('id', 1)->find()
master()
必须在链式开头,且后续所有操作(
where
find
)都在同一实例上调用 事务内读写混合 :无需额外指定,事务中所有操作(包括 SELECT)默认走主库,
Db::transaction(function () { Db::table('user')->find(); })
已足够 错误写法:
Db::master(); Db::table('user')->find()
—— 第一个
master()
返回新实例但没被使用,第二个
Db::table()
仍是默认连接。 调试读写分离是否真生效
getLastSql()
显示的只是 SQL 字符串,不体现执行位置。靠它判断走主还是从,100%误判。 真正有效的验证方式只有两个: 在从库执行
SHOW PROCESSLIST
,过滤应用服务器 IP,确认是否有来自 PHP 的 SELECT 连接 在
think/db/Connection.php
connect()
方法中加日志,打印
$config['hostname']
$isRead
标志 如果从库进程列表里始终看不到 SELECT,优先检查
'read'
是否为空、
'deploy'
是否遗漏、以及是否意外进入了事务或用了锁语句(如
lock(true)
)。

相关文章