Laravel 配置多数据库需在 config/database.php 中定义多个唯一命名的连接(如 mysql_secondary),并确保 .env 与配置一致;切换连接用模型 on() 或 DB::connection(),事务不跨连接。

怎么在 Laravel 中配置多个数据库连接
Laravel 支持多数据库连接,但不是靠“自动识别”或“开箱即用”,而是靠手动在 config/database.php 里定义多个键名不同的连接配置。每个连接必须有唯一的名字(比如 mysql、mysql_secondary、pgsql_reporting),且各自指定 driver、host、database 等完整参数。
常见错误是只改了 .env 里的 DB_DATABASE,却没在 config/database.php 里新增对应连接块 —— 这样 Laravel 根本不知道你要连哪个库。
- 不要复用
mysql键名来“覆盖”连接,要新建一个键,比如mysql_log - 每个连接的
prefix建议显式设为空字符串('')或按需设置,避免和主库表名冲突 - 如果用了读写分离,
read/write子数组里的连接必须也提前定义好,不能只写 host 不写完整配置
怎么在模型或查询中切换数据库连接
切换连接的本质是告诉 Eloquent 或 Query Builder 使用哪个配置键名,不是“动态改 host”。最常用的是 on() 方法,它作用于模型类或查询构造器实例。
注意:模型上用 on() 是静态调用,返回的是新绑定连接的查询构造器;而 connection() 是 DB 门面的方法,用于原生查询。
-
User::on('mysql_backup')->get()—— 指定模型使用mysql_backup连接 -
DB::connection('pgsql_reporting')->table('sales')->get()—— 原生查询走指定连接 - 别在模型里硬编码
$connection = 'mysql_secondary'后就以为万事大吉 —— 它只影响该模型默认连接,不解决临时切换需求 - 事务跨连接不生效:
DB::transaction()只对当前连接起作用,on()切换后的操作不在同一事务内
为什么 on() 不生效或报错 Database connection [xxx] not configured
这个错误几乎全是配置没对上:要么 config/database.php 里没加对应键,要么拼写大小写不一致(Laravel 区分大小写),或者配置被缓存没重刷。
典型场景是改了 .env 后直接跑命令,但忘了 php artisan config:clear 或 php artisan config:cache(后者会固化配置,改 .env 无效)。
- 检查
config/database.php是否真有你写的那个键,比如'mysql_log' => [...] - 运行
php artisan tinker,输入config('database.connections')看实际加载的连接列表 - 如果用
config:cache,每次改完config/database.php都得重新缓存,否则新连接不会被加载 - 别在测试环境用
sqlite连接名去连 MySQL 服务 —— 驱动不匹配也会报类似错误
什么时候该用连接池 / 多连接,而不是单库分表或视图
多数据库连接适合物理隔离明确的场景,比如主业务库 + 日志库 + 报表库,它们数据生命周期、访问频次、权限策略完全不同。不是为了解决单库性能瓶颈的首选方案。
滥用多连接反而增加维护成本:迁移要分别执行、Seeder 要指定连接、Eloquent 关联无法跨库(belongsTo 不能跨连接查)、软删除时间戳时区可能不一致。
- 报表类查询走只读从库,用
on('pgsql_reporting')显式指定,比在主库加慢查询更可控 - 日志写入独立库,可避免大流量写日志拖垮主业务事务响应
- 别为了“看起来高大上”把用户中心、订单、商品全拆成不同连接 —— 关联查询和事务一致性会立刻变成噩梦
事情说清了就结束











