ci4原生不支持主从自动读写分离,需手动配置'default'(主库)和'slave'(从库)两组连接,并在模型中显式调用db('default')或db('slave');强一致性读必须强制走主库,故障切换需依赖vip或配置中心,不可自动感知mha/orchestrator。

CodeIgniter 4 怎么配主从连接并自动读写分离
CI4 原生不支持主从自动路由,必须手动配置多个数据库组 + 在模型或查询构造器中显式指定连接。它没有内置的“读走从库、写走主库”智能分发逻辑。
实操建议:
- 在
app/Config/Database.php中定义两个独立的数据库组:一个叫'default'(主库),一个叫'slave'(从库),各自填好 host、username、database 等参数 - 确保从库配置了
read_only = ON(MySQL 层面),避免误写 - 写操作统一用
$this->db(即 default 组);读操作需显式调用db('slave')或DB('slave') - 不要依赖
$builder->from()自动识别读写——CI4 的 Query Builder 不会根据 SQL 类型切换连接
常见错误现象:写了 db('slave')->table('users')->get() 却查不到新数据,大概率是主从延迟未处理,或从库同步已断(SHOW SLAVE STATUS\G 中 Slave_IO_Running 或 Slave_SQL_Running 为 No)。
CI4 应用层怎么规避主从延迟导致的脏读
CI4 本身不提供一致性读控制,必须由业务代码兜底。刚写完就查,从库还没同步上来,这是最典型的“脏读”场景。
实操建议:
- 对强一致性要求高的读操作(如订单提交后立即查详情),强制走主库:
db('default')->table('orders')->where('id', $id)->get() - 若使用事务,且事务内含写+读,整个事务必须绑定主库连接(CI4 不支持跨连接事务,所以不能一半在 default、一半在 slave)
- 可封装一个简易路由函数,比如:
safe_read($table, $id, $force_master = false),内部根据$force_master决定用哪个连接 - 避免在控制器里混用
db()和db('slave')而不加注释——后期维护极易踩坑
注意:read_consistency = STRONG 这类参数是 OBProxy 或 ProxySQL 的能力,CI4 连接池里不存在这个概念。
CI4 能否配合 MHA / Orchestrator 实现故障自动切换
不能自动感知。CI4 的数据库连接一旦建立,就固定绑死在初始化时指定的 host 和 port 上,不会动态刷新 DNS 或重连新主库 IP。
实操建议:
- 必须配合外部机制:用 VIP(虚拟 IP)作为主库地址。MHA 切换时只漂移 VIP,CI4 配置里始终连
192.168.1.100(VIP),不用改代码 - 若用 DNS 方式,需确保 PHP 的
dns_cache_ttl设为 0(或极短),且应用重启/连接重建足够快;否则旧连接仍打向宕机的旧主 - 更稳妥的做法是把数据库地址抽到配置中心(如 Consul、etcd),CI4 启动时拉取,再配合健康检查定时刷新;但这已超出 CI4 自带能力范围
- 绝对不要在 CI4 中写“检测连接失败后自动切 slave 连接”——这等于把写请求发到只读从库,会直接报错
ERROR 1290 (HY000): The MySQL server is running with the --read-only option
真正容易被忽略的点是:CI4 的数据库连接默认是长连接(persistent),即使主库宕机,已有连接也不会主动断开重试,得靠连接池超时或应用重启才能释放。











