yii2虽无内置分库分表功能,但可通过多db组件配置、模型层动态绑定数据库(覆写getdb)、分表策略(动态tablename)及分片路由服务实现灵活的分库分表架构。

Yii2本身不内置分库分表功能,但通过灵活的组件机制和模型层扩展能力,能自然支撑多库、多表、分片式架构。关键在于把数据库连接、表名、查询路由这些环节从“固定配置”变成“可编程逻辑”。
多数据库连接配置是基础
先在config/web.php或main-local.php中定义多个DB组件:
-
主库用于写操作和核心事务,如
db指向orders_main -
从库用于读操作,如
dbSlave1、dbSlave2,配合读写分离中间件或手动路由 -
专用库如权限库
auth_db、日志库log_db,按业务域隔离
每个组件都是独立的yii\db\Connection实例,支持不同主机、端口、字符集甚至不同数据库类型(MySQL/PostgreSQL)。
模型层动态绑定数据库
ActiveRecord默认用Yii::$app->db,但可通过覆写getDb()方法切换连接:
- 订单模型指定用主库:
return Yii::$app->db; - 用户统计模型走从库:
return Yii::$app->dbSlave1; - RBAC权限模型强制走
auth_db,并在authManager配置中显式声明四张表的全限定名(如auth_db.auth_item)
这样既保持模型复用性,又实现物理隔离,避免跨库JOIN带来的性能与事务问题。
分表策略落地靠tableName()动态生成
水平分表最常用,核心是让static tableName()返回带后缀的实际表名:
-
时间分片:日志表按月拆分,
log_202607、log_202608,用date('Ym')计算 -
ID哈希分片:订单按
order_id % 16散列到16张表,确保数据均匀且路由确定 -
业务维度分片:商户订单按
merchant_id % 8分,天然支持租户隔离
注意:分表后find()->all()只查单表,跨表聚合需用UNION或应用层合并——Yii2的Query Builder支持union()链式调用,可动态拼接多个子查询。
分片路由与一致性保障
单纯分表不解决路由逻辑,需配套设计:
- 封装一个
ShardRouter服务,输入分片键(如user_id),输出目标库+表名,供模型调用 - 写操作必须带分片键,否则无法定位;读操作若无键,走广播查询或默认库
- 分布式ID生成器(如Snowflake)替代自增主键,避免分表后ID冲突和热点问题
- 关键事务(如下单扣库存)尽量控制在单一分片内完成,避免跨分片两阶段提交
不复杂但容易忽略











