ThinkPHP 6.3 在 PHP 7.2 环境下实现主从读写分离,需在 database.php 中明确定义 mysql_master 和 mysql_slave 连接键名,type 不可省略,权限与配置须严格对应,并执行 php think clear:config 清除配置缓存。

ThinkPHP 7.2 不存在——当前(2026年9月)最新稳定版是 ThinkPHP 6.3,而 PHP 7.2 是运行环境,不是框架版本。你实际要配的是:**在 PHP 7.2 环境下,用 ThinkPHP 6.x 实现数据库主从读写分离**。
下面直接说怎么做、为什么这么设、以及哪些地方一错就查不出数据。
database.php 中必须定义两个命名连接
ThinkPHP 不会自动识别“主库/从库”,它只认你 config/database.php 的 connections 数组里明确声明的键名。没声明,Db::connect('slave') 就会抛出 Connection not found: slave。
必须这样写(注意键名全小写、无点号、不重复):
'connections' => [
'mysql_master' => [
'type' => 'mysql',
'hostname' => '192.168.1.10',
'database' => 'myapp',
'username' => 'master_user',
'password' => 'xxx',
'hostport' => '3306',
'charset' => 'utf8mb4',
'prefix' => 'tp_',
],
'mysql_slave' => [
'type' => 'mysql',
'hostname' => '192.168.1.11',
'database' => 'myapp',
'username' => 'slave_user',
'password' => 'yyy',
'hostport' => '3306',
'charset' => 'utf8mb4',
'prefix' => 'tp_',
],
],
关键点:
-
type字段不能省,写成mysqli或空字符串会导致Class 'PDO' not found - 两个库的
database名通常一致(主从同步的是同一库),但username/password应不同,且从库账号只需SELECT权限 - 改完必须执行
php think clear:config,否则缓存旧配置,死活不生效
模型绑定从库连接时,$connection 值必须匹配键名
如果你希望某个模型(比如 UserLog)默认走从库查询,就在模型类里写:
立即学习“PHP免费学习笔记(深入)”;
<?php
namespace app\model;
use think\Model;
class UserLog extends Model
{
protected $connection = 'mysql_slave';
}
这里 $connection = 'mysql_slave' 的值,必须和 database.php 里 connections 数组的键完全一致。大小写、下划线、拼写错一个字符,查询就回退到默认连接(通常是 master),而且不会报错——你只会发现“明明配了从库,怎么还是查主库?”
验证方式很简单:在控制器里临时加一句
dump((new \app\model\UserLog())->getConnection()->getConfig()['hostname']);
输出的 IP 应该是从库地址。如果不是,立刻检查键名是否一致、配置是否被缓存、模型文件是否被正确加载。
读写分离不能靠框架自动判断,得手动控制
ThinkPHP 没有内置“写操作自动走 master、读操作自动走 slave”的智能路由。所谓“读写分离”,本质是你自己决定哪条语句发给哪个库。
常见做法:
- 写操作:一律用默认连接或显式指定
Db::connect('mysql_master') - 读操作:用模型绑定(如上)或临时切换
Db::connect('mysql_slave')->table('log')->select() - 事务内禁止切库:一旦
Db::startTrans(),所有语句必须在同一连接上执行,跨库事务会失败 - 连贯操作如
where()->order()->limit()必须在同一个Db::connect()实例上调用,不能中间换连接
容易踩的坑:Db::connect('mysql_slave')->table('user')->find(1) 是从从库查;但如果你之后又调了 Db::name('user')->update(...),这个 update 就走默认连接(master),而不是你刚用的那个 slave 实例——因为 Db::name() 是静态方法,跟前面的实例无关。
从库延迟导致查不到最新数据,这不是配置问题
MySQL 主从复制有天然延迟(Seconds_Behind_Master),尤其在高写入场景下可能达数百毫秒。这意味着:用户刚注册(写 master),马上去个人页(读 slave),可能查不到自己的资料。
这不是 ThinkPHP 配置能解决的,应对方式只有:
- 强一致性读:关键路径(如刚提交后立即查看)强制走主库,例如
Db::connect('mysql_master')->table('user')->find($id) - 应用层加缓存:写完后主动更新 Redis,读时优先查缓存
- 监控
SHOW SLAVE STATUS\G中的Seconds_Behind_Master,持续大于 0 要查网络、磁盘 I/O 或大事务阻塞
别试图在框架里加“等待从库追平”逻辑——既不可靠,又拖慢响应。



















