CodeIgniter 4 不内置读写分离,需手动配置多数据库组并在业务层显式调用从库执行读操作、主库执行写操作,事务强制走主库,从库只读且存在同步延迟。

CodeIgniter 4(CI4)本身不内置主从读写分离能力,所有数据库操作默认走单一连接。想实现读写分离,必须手动干预连接路由逻辑——要么改写 Query 或 BaseBuilder 类,要么在业务层显式指定连接,要么用中间件/服务层做请求分发。没有“开箱即用”的配置项。
CI4 中如何强制读操作走从库
CI4 的 $db->table()->get()、$db->query()(SELECT)等默认使用 default 连接组,不会自动识别读/写意图。要让读走从库,得主动切换连接:
- 定义多个数据库组:在
app/Config/Database.php中配置default(主库)和slave(从库)两个组,确保server-id、host、username等参数正确指向真实从库实例 - 读操作显式调用从库连接:
$slaveDB = \Config\Database::connect('slave');,再用$slaveDB->table('users')->get() - 避免复用
$this->db实例:Controller 或 Model 中若已注入$db(来自 default 组),不能直接用于读从库,必须重新 connect - 注意事务上下文:一旦开启事务(
$db->transStart()),后续所有查询都绑定到该连接,即使你写了 SELECT 也回不到从库——事务强制走主库
写操作为什么不能走从库
从库通常设为 read_only = 1,任何写语句(INSERT、UPDATE、DELETE、CREATE TABLE)都会触发 MySQL 错误:ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement。这不是 CI4 的限制,是 MySQL 层的硬约束。
更关键的是,即使临时关闭 read_only,从库执行写操作会破坏主从复制链路:从库 binlog 可能被启用,但其写入不会同步回主库,且可能与主库变更冲突,导致数据不一致或复制中断。
所以 CI4 应用里所有写操作必须明确使用 default 连接组,且不能混用 slave 连接执行写语句——哪怕只是测试,也会立即报错或埋下隐患。
数据迁移时主从延迟怎么处理
CI4 执行完 $db->insert() 后立刻用 $slaveDB->get() 查询,大概率查不到刚插入的数据,因为从库同步有延迟(毫秒到秒级)。这不是代码 bug,而是 MySQL 主从异步复制的本质特征。
- 对“读己所写”强一致场景(如注册后跳转个人页),必须绕过从库:直接用主库连接查,或加缓存标记(如 Redis key)暂存新数据
- 批量迁移脚本(如导入百万用户)应禁用从库查询,全程走主库,避免因延迟导致校验失败
- 如果迁移过程需验证从库同步状态,可用
SHOW SLAVE STATUS\G查Seconds_Behind_Master,但 CI4 无法直接获取该值——需通过mysqli或原生 PDO 手动连从库执行 - 不要依赖
SLEEP()等粗暴等待:延迟不可控,且浪费连接资源
真正麻烦的不是配置多一个数据库组,而是业务逻辑里每处 SELECT 都得判断是否允许接受延迟——有些地方能忍 500ms,有些地方必须立刻看到结果。这个决策点不在 CI4 框架里,而在你自己的服务层设计中。

















