Laravel不支持运行时动态切换数据库驱动,但可通过配置多个连接名实现多库、读写分离和租户隔离;所有连接需在config/database.php的'connections'中定义,连接名全局唯一,'driver'可不同,切换仅限于已注册的连接名。

Laravel 本身不支持运行时动态切换数据库驱动(比如从 mysql 切到 pgsql),但可以动态切换连接名(connection name)——这是实现多库、读写分离、租户隔离的正确路径。
怎么在配置里定义多个数据库连接
所有连接都写在 config/database.php 的 'connections' 数组里,每个键是连接名(如 'mysql'、'mysql_read'、'tenant_123'),值是完整配置。关键点:
- 连接名必须全局唯一,不能重复
-
'driver'决定底层用哪个 PDO 驱动,同一应用中不同连接可使用不同驱动(比如主库mysql,日志库sqlite) -
'database'和'host'等参数可从环境变量读取,方便多环境管理 - 读写分离不是靠“自动识别 SELECT/INSERT”,而是靠显式指定连接名或通过连接池路由
return [
'default' => env('DB_CONNECTION', 'mysql'),
'connections' => [
'mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
],
'mysql_read' => [
'driver' => 'mysql',
'host' => env('DB_READ_HOST', '192.168.1.10'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
],
],
];
如何在模型或查询中切换连接名
切换的是连接名(connection name),不是驱动类型。Laravel 的 DB::connection() 和模型的 $connection 属性都只接受已注册的连接名。
- 全局临时切换:
DB::connection('mysql_read')->table('users')->get() - 模型级固定连接:在 Eloquent 模型里设
protected $connection = 'mysql_read'; - 运行时动态绑定(适合租户场景):
User::on('tenant_'.$tenantId)->get(),前提是该连接名已在config/database.php或运行时用Config::set()注册过 - 注意:
on()只影响当前查询,不会改变模型默认连接;未调用on()时仍走$connection或全局default
读写分离怎么配才真正生效
Laravel 自带的读写分离机制,依赖你明确声明哪些连接是 “read”、哪些是 “write”,并统一挂到一个逻辑连接名下(如 'mysql'),而不是靠中间件或 DB 类自动判断 SQL 类型。
- 在
config/database.php中,把'mysql'改成数组形式,包含'read'和'write'子键 - 每个子键下可定义多个 host,Laravel 会随机选一个读库执行
SELECT - 所有非
SELECT查询(INSERT/UPDATE/DELETE)强制走'write'配置 - 这个机制只对
DB::table()和未指定$connection的 Eloquent 生效;一旦用了on('xxx'),就绕过读写分离逻辑
'mysql' => [
'read' => [
'host' => ['192.168.1.10', '192.168.1.11'],
],
'write' => [
'host' => ['192.168.1.5'],
],
'driver' => 'mysql',
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
],
动态注册连接名(比如按租户生成)要小心什么
可以用 Config::set('database.connections.tenant_123', [...]) 在请求中注册新连接,但有硬性限制:
- 必须在第一次调用
DB::connection('tenant_123')之前完成注册,否则 Laravel 会报InvalidArgumentException: Database [tenant_123] not configured. - 连接配置里的
'database'、'username'等字段不能含非法字符,尤其注意租户 ID 是否被注入恶意内容 - 高频创建连接名可能引发内存泄漏,建议配合连接池或缓存连接配置,而不是每次请求都
Config::set() - 如果你需要频繁切换且连接数多,更稳妥的做法是预定义一组连接名(如
tenant_001~tenant_100),启动时全部加载
驱动类型是静态绑定的,改不了;连接名才是你真正能控制的开关。别试图在运行时把 mysql 驱动替换成 sqlsrv,那会直接报错。











