database.php 是唯一生效位置,多库必须在 'connections' 中定义唯一命名连接,default 连接必须完整;db::connect('name') 切换连接,db::name() 始终走默认连接;读写分离需同时满足 deploy=>1、rw_separate=>true 且 read/write 同级;模型通过 $connection 属性绑定指定连接。

database.php 是唯一生效位置,其他地方写的数据库配置(比如 .env 里只配一个库、模型里硬编码)都无法覆盖或扩展多库能力。默认连接必须存在且完整,否则 Db:: 调用直接报错。
如何在 config/database.php 中正确定义多个独立数据库连接
ThinkPHP 6 不支持「写多个同名连接」或「在 default 下堆数组」,所有额外数据库都必须作为命名连接注册进 'connections' 数组,且键名全局唯一(不能叫 mysql、pgsql 等驱动名)。
常见错误现象:Db::connect('user')->table('essential_information')->select() 报错“Connection not found”,实际是因为 'user' 没在 connections 里定义,或者键名拼错了。
-
'connections'必须是关联数组,每个子项是一个完整连接配置(含type、hostname、database、username、password等) -
prefix建议设为空字符串(''),跨库时避免表名被自动拼接前缀导致查不到 - 不同连接的
charset可以不同,比如主库用utf8mb4,日志库用latin1,但需确保 MySQL 服务端支持 - 如果连接的是远程从库,建议加
'params' => [PDO::ATTR_PERSISTENT => true]减少连接开销
Db::connect() 和 Db::name() 的行为差异与误用陷阱
Db::name('user') 永远走当前默认连接(即 config/database.php 中 'default' 指向的那个连接),它不认你定义的 'user' 或 'admin' 连接名;而 Db::connect('user') 才真正切换到名为 'user' 的那个连接配置。
常见错误写法:Db::connect('user')->name('essential_information')->select() —— 表面看没问题,但一旦中间插入 ->cache() 或 ->useSoftDelete(),底层可能因连接复用逻辑丢失上下文,返回主库数据。
- 推荐写法:
$db = Db::connect('user'); $db->table('essential_information')->select(); -
table()直传真实表名,不依赖prefix,跨库更可控;name()会自动拼前缀,容易出错 - 事务只在单连接内有效:
Db::connect('a')->startTrans()和Db::connect('b')->startTrans()是两个完全隔离的事务,无法跨库提交或回滚
主从分离配置为何不生效?关键开关和结构约束
主从不是“写了 read 就自动轮询”,TP6 必须同时满足三个条件才触发读写分离逻辑:存在有效的 default 连接、'deploy' => 1、'rw_separate' => true,且 read 和 write 必须是同级键(不能塞在某个连接配置内部)。
常见错误现象:SELECT 语句始终走主库,read 配置像没写一样。大概率是漏了 'deploy' => 1,或者把 read 写在了 'connections.mysql.read' 里(TP6 不识别这种嵌套)。
-
'deploy' => 1是总开关,缺了它整个读写分离模块不会加载 -
'write'只能是单个数组,不能是数组套数组;'read'可以是单个数组(一个从库)或数组套数组(多个从库,TP 随机选) - 带锁查询(如
->lock(true))、事务内所有查询、FOR UPDATE原生 SQL,全部强制走主库,这是框架级一致性保障,无法绕过 - SSL 配置只能通过
params数组传入,键名必须是 PDO 常量(如PDO::MYSQL_ATTR_SSL_CA),路径必须是服务器绝对路径
模型类如何绑定指定数据库连接
模型默认只认 default 连接,即使你在 database.php 里定义了 'log_db',app\model\UserLog 类也不会自动连过去。最稳的方式是在模型类中显式声明 protected $connection = 'log_db';。
这个属性优先级高于全局配置,且在模型初始化阶段就绑定,比重写 getConnection() 方法更轻量、更可靠。
- 不要在构造函数里调用
Db::connect()并赋值给属性——模型实例化早于连接初始化,会报错 - 如果该模型需要动态切换连接(比如按用户 ID 分库),应重写
getConnection()方法,但要注意缓存和连接复用问题 -
$connection的值必须是connections中已定义的键名,大小写敏感,且不能含空格或特殊字符
prefix 默认值和 deploy 开关,它们不报错,但让多库逻辑彻底失效。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











