ci4不内置读写分离与数据归档功能,需开发者手动实现:配置主从数据库组、显式调用db('write')/db('read')、强一致读强制走主库、归档通过定时任务执行搬移+清理。

CI4(CodeIgniter 4)本身不内置读写分离或数据归档能力,所有相关功能必须由开发者在框架层主动控制——这意味着你不能依赖 CI4 自动识别 SELECT 或 INSERT 并路由到不同数据库,也不能靠它自动触发归档逻辑。
CI4 中手动实现读写分离的关键点
CI4 的 Database 类支持多数据库连接,但默认所有查询都走同一连接。要实现读写分离,必须显式切换连接实例,并配合业务逻辑做判断。
- 定义两个数据库组:一个叫
write(主库),一个叫read(从库),在app/Config/Database.php中配置好各自DSN或连接参数 - 在模型或服务类中,用
db('write')获取写连接,db('read')获取读连接;不要复用同一个$db实例 - 避免在事务中混用读写连接:
db('write')->transStart()后的所有操作(包括SELECT)必须继续用db('write'),否则会报错或数据不一致 - CI4 没有 AOP 或注解机制,无法像 Spring Boot 那样用
@ReadOnly自动切库,所有路由逻辑必须手写、显式调用
主从延迟下如何保证关键读取一致性
从库同步总有延迟,用户刚提交订单就查“我的订单”,很可能查不到。CI4 不提供 Hint 或强制主库读的封装,需自行处理。
- 对强一致性场景(如刚写完立刻查),直接用
db('write')执行SELECT,哪怕只是读 - 可封装一个
forceMasterRead()方法,在模型中统一调用,避免散落各处的db('write') - 不要依赖
lastInsertId()后立刻用db('read')查新记录——该 ID 在从库可能尚未同步 - 若用缓存(如 Redis)暂存刚写入的数据,注意缓存过期时间要略长于主从最大延迟(比如设为 3 秒),否则缓存击穿后仍会打到从库
CI4 数据归档不是“自动迁移”,而是按需清理+冷备
CI4 没有归档调度器或生命周期管理,所谓“归档”本质是应用层发起的两步操作:把旧数据搬走 + 把原表删掉。它不等同于数据库自身的归档日志(如 MySQL 的 binlog)或达梦的 TIMELY 归档。
- 归档动作必须由定时任务(如 Linux
cron调用php spark archive:orders)触发,CI4 不提供内置调度 - 典型流程:
db('write')->table('orders')->where('created_at get()->getResult()→ 写入归档表或导出 CSV →db('write')->table('orders')->where(...)->delete() - 归档表建议建在独立数据库或 schema 中,避免与在线业务争抢锁和 I/O;不要和主表同名、仅靠前缀区分(如
orders_archive),否则容易误操作 - 删除前务必确认从库已同步完成(可通过
SHOW SLAVE STATUS的Seconds_Behind_Master判断),否则归档后从库会丢失这部分数据
真正麻烦的不是代码怎么写,而是归档窗口期和主从同步状态的耦合判断——CI4 不感知数据库复制状态,这部分必须你自己用原生 SQL 或运维接口(如 DM 的 SELECT * FROM V$ARCHIVE_STATUS)去查,再决定是否执行 delete。











