Yii2支持多数据库配置与动态切换,需在components中定义多个DB组件(如db_slave、db_log),通过Yii::$app->get('dbX')或AR模型重写getDb()方法显式调用指定连接,事务和迁移需按组件单独处理。

Yii2 支持多数据库配置和运行时动态切换连接,关键在于正确配置多个 DB 组件,并在代码中通过 Yii::$app->get('dbX') 或 new Connection() 显式调用指定连接,而非依赖默认 db 组件。
1. 配置多个数据库组件
在 config/web.php 或 config/main.php 的 components 中定义多个数据库连接,例如:
'components' => [
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=main_db',
'username' => 'root',
'password' => '',
'charset' => 'utf8mb4',
],
'db_slave' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=192.168.1.100;dbname=backup_db',
'username' => 'reader',
'password' => 'pass123',
'charset' => 'utf8mb4',
],
'db_log' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=log_db',
'username' => 'logger',
'password' => 'logpass',
'charset' => 'utf8mb4',
],
],
每个组件使用唯一 ID(如 db_slave、db_log),避免与默认 db 冲突。
2. 在模型或控制器中动态使用指定数据库
不修改模型的默认连接,而是显式获取并传入连接对象:
- 查询时指定连接:
$users = User::find()->using('db_slave')->all(); - 执行原生 SQL:
Yii::$app->db_slave->createCommand("SELECT * FROM users")->queryAll(); - 事务跨库需手动管理:
Yii::$app->db_log->beginTransaction(); - AR 模型绑定特定连接(推荐):在模型类中重写
getDb()方法
示例(绑定日志模型到 db_log):
class Log extends \yii\db\ActiveRecord
{
public static function getDb()
{
return \Yii::$app->db_log;
}
}
// 使用方式
Log::find()->where(['level' => 'error'])->all();
3. 运行时动态切换连接(按条件选库)
适合读写分离、分库分表等场景。可封装一个工厂方法或行为:
- 根据请求参数选库:
$db = Yii::$app->get('db_' . ($isRead ? 'slave' : 'master')); - 按用户 ID 哈希分库:
$shardId = $userId % 3; $db = Yii::$app->get("db_shard{$shardId}"); - 结合事件或行为,在
ActiveRecord::init()中动态设置$this->db
注意:动态切换不改变全局 Yii::$app->db,只影响当前操作所用连接实例。
4. 注意事项与常见问题
- 迁移命令默认只作用于
db组件,多库迁移需加--db=db_slave参数 - 事务不能跨多个 DB 组件,每个
Connection实例维护独立事务上下文 - 连接池、超时、重连等配置需在各组件中单独设置,无法全局继承
- 调试时可通过
Yii::info(Yii::$app->db_slave->getActive(), 'db');查看是否已激活
不复杂但容易忽略细节,核心是“声明即配置,调用即切换”。


















