yii2多数据库必须为每个库注册独立组件(如db2),跨库关联需分步查询并显式指定getdb(),跨库事务不可用,须用应用层补偿机制。

Yii2 的数据库配置不是“设一个就行”,而是必须按组件名显式注册,否则第二个库永远用不上。
db 组件名不能重复,每个库要独立注册
Yii2 不支持在 config/db.php 里塞多个数组然后自动识别——它只认 components 下的键名。你写两个 db,后一个会直接覆盖前一个。
- 正确做法:在
config/web.php(或common/config/main.php)的components里分别注册,比如:'db' => [...]、'db2' => [...]、'dbStats' => [...] - 常见错误:把所有 DSN 都塞进同一个
db数组里,或用array_merge()浅拷贝配置,漏掉charset或tablePrefix - 不同库的
tablePrefix必须各自配,不能共用全局前缀——否则副库查表时会拼错名,报SQLSTATE[42S02]
模型怎么指定用哪个数据库连接
ActiveRecord 默认只用 db 组件。想让某个模型连 db2,必须重写它的 getDb() 方法。
- 示例:
public static function getDb() { return \Yii::$app->db2; } - 别在
relations里定义跨库关联(比如hasOne(Order::class)),MySQL 本身不支持跨库 JOIN,with()会静默失败或抛出表不存在错误 - 如果只是临时查一次,也可以不用改模型,直接用:
\Yii::$app->db2->createCommand('SELECT * FROM order')->queryAll()
事务跨库根本不可用,得自己兜底
$transaction = \Yii::$app->db->beginTransaction() 只锁住当前连接的库。对 db2 的操作完全不在事务范围内,既不会回滚,也可能造成数据不一致。
- MySQL 本地事务天然不跨连接,Yii2 的
Transaction类只是封装了单个Connection实例 - 真要保证多库数据一致性,只能用应用层补偿:先提交主库,再调副库;失败时手动逆向操作(比如发消息通知、记录日志、定时对账)
- 别试图用
FEDERATED引擎绕过限制——生产环境基本没人用,维护成本高、性能差、权限难控
最常被忽略的一点:配置里写的 charset 必须和实际数据库建库时的字符集严格一致。比如 MySQL 用的是 utf8mb4,但配置里写成 utf8,emoji 就存不进去,且错误往往延迟到插入时才暴露。











