CodeIgniter原生不支持数据库负载均衡,仅能通过手动配置多组连接并在业务层显式切换实现读写分离,无自动路由、健康检查或故障转移能力。

CodeIgniter 原生不支持数据库负载均衡(如读写分离或主从自动分发),它没有内置的连接池、健康检查或查询路由机制。所谓“配置实现负载均衡”,实际只能做到**手动多连接 + 业务层分流**,不能替代 MySQL Proxy、ProxySQL 或应用网关层方案。
database.php 中定义多个数据库组只是静态声明
你可以在 application/config/database.php 里定义 master 和 slave 两组:
$db['master'] = [ /* 写库配置 */ 'hostname' => '10.0.1.10', 'database' => 'myapp', 'dbdriver' => 'mysqli', /* ... */ ]; $db['slave'] = [ /* 读库配置 */ 'hostname' => '10.0.1.11', 'database' => 'myapp', 'dbdriver' => 'mysqli', /* ... */ ];
但这只是把连接参数存下来,$active_group = 'master' 仍只生效一个;CI 不会自动识别 SELECT 就连 slave、INSERT 就连 master。
- 所有模型默认用
$this->db,它始终绑定$active_group指向的那一个 - 想切到
slave,必须显式调用$this->load->database('slave', TRUE)并保存返回对象 - 没有故障转移逻辑:如果
slave宕机,database()会直接报错,不会 fallback 到 master
手动切换连接需在每个需要读操作的模型方法中显式加载
例如在用户模型中做读操作时,不能依赖默认连接,得自己加载从库:
class User_model extends CI_Model
{
public function get_list()
{
$slave = $this->load->database('slave', TRUE); // 第二个参数 TRUE 表示返回对象而非单例
return $slave->get('users')->result();
}
<pre class="brush:php;toolbar:false;">public function create($data)
{
return $this->db->insert('users', $data); // 默认用 master($active_group)
}}
容易踩的坑:
- 忘记传
TRUE→ 返回的是同一个单例,后续调用可能污染连接状态 - 事务中混用
$this->db和$slave→ MySQL 不支持跨连接事务,会静默失败 - 未统一管理连接生命周期 → 频繁
load->database()可能导致连接数暴涨(尤其高并发时)
无法通过 config 自动路由,必须改写核心逻辑或加中间层
若真要接近“负载均衡”效果,有两条现实路径:
- 重写
CI_DB_driver的query()方法,在执行前根据 SQL 类型(SELECT/UPDATE)动态选择连接对象 —— 但 CI 3.x 的 DB 类设计为单例绑定,强改易引发兼容问题 - 封装一个
DBRouter库,对外提供read()/write()接口,内部维护两个连接实例,并由上层业务决定何时调用哪个 —— 这才是可控、可测的做法 - 更稳妥的做法是:把读写分离逻辑下沉到服务层,模型只负责执行,不关心连哪台机器;配置文件只存地址列表,不参与路由决策
注意:failover 数组仅用于同组内备用主机(比如主库挂了切到另一个主库),不是用来做读写分离的,填了也没用。
真正的负载能力取决于你怎么调度连接、怎么处理失败、是否缓存连接句柄——这些都不在 config 范围内。别指望靠改几行 $db['xxx'] 就实现高可用读写分离。











