codeigniter实现读写分离的核心是配置多个数据库连接并在框架层按操作类型自动路由:一、在database.php中配置master(写)和slave1等从库连接,autoinit设为false;二、通过自定义my_model统一管理read_db/write_db属性,使子类模型透明调用;三、进阶可重写db_driver的query()方法,依sql关键词(select/insert等)自动分发至对应库;四、需验证主从延迟、实现从库宕机fallback及主库故障应急预案。

CodeIgniter 实现读写分离,核心是配置多个数据库连接,并在代码中按操作类型(读 or 写)自动选用对应连接。它不依赖数据库中间件,而是通过框架层控制,适合中小规模项目快速落地。
一、配置主库与从库连接
打开 application/config/database.php,在已有 $db['default'] 的基础上,新增一个专用于写操作的数据库配置(如 'master'),再保留或新增一个/多个只读连接(如 'slave1'、'slave2'):
- 主库(写):配置真实主服务器地址、账号、权限(必须含 INSERT/UPDATE/DELETE)
- 从库(读):可配一台或多台,IP 指向从服务器,账号只需 SELECT 权限
-
注意 autoinit:建议设为
FALSE,避免每次加载都连库;连接由业务触发时才建立
示例片段:
$db['master'] = array(
'hostname' => '192.168.1.100',
'username' => 'db_admin',
'password' => 'xxx',
'database' => 'myapp',
'dbdriver' => 'mysqli',
'autoinit' => FALSE,
// 其他参数同 default
);
<p>$db['slave1'] = array(
'hostname' => '192.168.1.101',
'username' => 'db_reader',
'password' => 'yyy',
'database' => 'myapp',
'dbdriver' => 'mysqli',
'autoinit' => FALSE,
);</p>
二、封装统一的数据访问入口
手动在每个 Model 里反复调用 $this->load->database('master') 和 $this->load->database('slave1') 容易出错且难维护。推荐做法是创建一个基础 Model 类(如 application/core/MY_Model.php),集中管理读写路由逻辑:
- 重写
__construct(),根据当前请求方法或 SQL 类型决定加载哪个库 - 提供
$this->read_db和$this->write_db两个属性供子类使用 - 对简单查询(如
get()、get_where())默认走从库;对insert()、update()、delete()强制走主库
这样后续所有业务 Model 继承 MY_Model 即可,无需关心具体连哪台机器。
三、SQL 类型自动识别(进阶透明化)
若希望完全对开发者透明(即仍用 $this->db->get() 就自动走从库,$this->db->insert() 自动切主库),需轻微扩展框架行为:
- 在 application/core/MY_Loader.php 中重写
database()方法,支持动态加载不同驱动 - 在 application/core/database/DB_driver.php 中覆盖
_execute()或query(),解析 SQL 开头关键词(如 INSERT/UPDATE/DELETE → 主库;SELECT/SHOW → 从库) - 首次读操作随机选一台从库并缓存连接句柄,后续读复用该连接;写始终锁定主库
此方式无需修改任何 Model 代码,但需确保 SQL 书写规范(例如避免 SELECT * FROM table WHERE id IN (SELECT ...) 这类嵌套写法干扰判断)。
四、验证与容错处理
上线前务必验证主从同步延迟和连接稳定性:
- 在从库执行
SHOW SLAVE STATUS\G,检查Seconds_Behind_Master是否长期为 0 或极小值 - 模拟从库宕机:临时停掉 slave1 MySQL 服务,确认系统能自动 fallback 到 slave2 或降级走主库读(需在 DB_driver 层加入重试逻辑)
- 主库故障时,应有应急预案(如人工切换
$active_group = 'slave1'并开启写权限),不建议全自动提升从库为主库
读写分离不是银弹,合理配置 + 明确边界 + 持续监控,才能真正提升数据库吞吐能力。











