Db::connect() 创建新连接实例而非切换默认库,后续 Db::table() 等静态调用仍走默认库;须链式调用如 Db::connect('mysql2')->table('user')->select() 才生效。

ThinkPHP 6 中 Db::connect() 不是“切换默认库”,而是新建连接实例——后续所有 Db::table()、Model::find() 仍走默认库,除非你显式用返回的对象链式调用。
Db::connect('mysql2') 后查不到数据?先检查 database 配置项
错误现象:调用 Db::connect('mysql2')->table('user')->select() 报 PDOException: SQLSTATE[HY000] [1049] Unknown database 或 No database selected。
根本原因不是连不上 MySQL 服务,而是配置里漏了 'database' 字段,或填的库名在 MySQL 中压根不存在。
ThinkPHP 不会帮你创建数据库,只负责连接已存在的库。
- 检查
config/database.php中'mysql2'连接配置是否包含'database' => 'my_app_v2',拼写必须完全一致(Linux 下大小写敏感) - 确认 MySQL 用户对目标库有
SELECT权限:仅能连上host≠ 能操作该库 - 若用了
unix_socket,确保路径真实存在且 PHP 进程可读 - 错误码对照:
[1045]是账号密码错;[1049]就是库名不存在
模型类里设 $connection = 'mysql2' 为什么没生效?
现象:在模型顶部写了 protected $connection = 'mysql2';,但 User::find(1) 还是从默认库查。
这是因为该属性只在模型类首次加载时读取一次,后续运行中改配置、换租户 ID 都不会重新加载它。
- 如果模型继承自基类,务必在子类中显式重写
$connection,否则会被父类值覆盖 - 它不解决跨库关联问题:
User::with('profile')中的Profile模型仍按自己声明的$connection执行,不会自动跳去同库 - 迁移命令
php think migrate:run完全不识别模型的$connection,只按database.default配置执行
高频切换数据库时连接数暴涨?必须复用 Db 实例
现象:循环中写 for ($i = 0; $i table('xxx')->insert([...]); },MySQL 很快报 Too many connections。
因为每次 Db::connect() 都新建一个 PDO 实例,不复用、不回收。
立即学习“PHP免费学习笔记(深入)”;
- 正确做法:提前赋值复用 ——
$logDb = Db::connect('log');,之后所有操作都用$logDb->table(...)->insert() - 绝不在 for 循环、foreach 或高频请求中反复调用
Db::connect(),哪怕参数一样 - 事务只能在单个
Db实例内生效:$db1->startTrans()和$db2->commit()完全无关,别指望它们协同 - 多租户场景下,不能靠改
$connection实现请求级隔离——得用Db::setConnectConfig('tenant_123', $config)动态注册 +Db::name()->connect('tenant_123')显式调用
Db::table('user') 永远走默认连接,和之前有没有 Db::connect() 无关
这是最常被忽略的一点。很多人写了 Db::connect('mysql2'),以为接下来整段逻辑都切过去了,结果下一行 Db::table('log')->select() 还是从主库查。
因为 Db::table()、Db::name()、Model::find() 这些静态入口,永远绑定默认连接,不继承前序调用的上下文。
- 想换库,必须用
Db::connect('mysql2')->table('user')->select()这种完整链式调用,少一个->table()或中间断开,就回主库 - 事务、查询构造器、软删除等所有功能,都依赖当前
Db实例的连接上下文,不是全局状态 - 复杂业务建议封装成服务类,把几个预热好的
$dbMain、$dbLog、$dbTenant当作成员变量管理,避免临时 new 或重复 connect



















