Laravel怎么配置多数据库连接_Laravel动态切换数据库驱动与读写分离【方案】

12次阅读

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

Laravel怎么配置多数据库连接_Laravel动态切换数据库驱动与读写分离【方案】

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,那会直接报错。

text=ZqhQzanResources