CI4需手动配置主从库:在app/Config/Database.php中定义default(主库,设'writeOnly'=>true)和slave(从库,设'readOnly'=>true),查询走slave、写操作走default,事务仅支持主库,主从延迟时关键读必须强制走主库,数据清洗应在业务逻辑层而非ORM层处理。

CodeIgniter 4(CI4)本身不内置主从读写分离支持,必须靠手动配置多数据库连接 + 应用层路由控制;数据清洗不是 CI4 的职责,得在业务逻辑或 ETL 阶段做,不能指望 ORM 自动处理脏数据。
CI4 怎么配主库和从库连接
CI4 的 Database 类不区分读/写连接,得自己定义两套配置:一个叫 default(主库),另一个叫 slave(从库),都写进 app/Config/Database.php 里。
-
default配置里必须设'writeOnly' => true(虽无强制校验,但这是约定),并确保'hostname'指向主库 IP -
slave配置里加'readOnly' => true,且'hostname'指向从库;server-id和read_only=1得在 MySQL 侧配好,CI4 不管这个 - 别复用同一个
DSN或共用database名——主从库名可以相同,但连接参数必须物理隔离
怎么让查询走从库、写操作走主库
CI4 没有自动 SQL 路由,所有分发逻辑得手写。最简方式是封装一个 DB 工具类,暴露 write() 和 read() 方法,内部调用 db_connect('default') 或 db_connect('slave')。
- 写操作一律用
$this->db = db_connect('default');,再调insert()/update()等 - 读操作统一走
$this->db = db_connect('slave');,注意query()、table()->get()都要基于这个实例 - 别在 Model 里硬编码连接名——Model 应接收连接实例,而不是自己 new 出来,否则没法单元测试
- 事务只能跑在主库上:
startTransaction()必须在default连接上调用,从库不支持事务
主从延迟下查不到刚写入的数据怎么办
MySQL 主从同步是异步的,Seconds_Behind_Master 可能为 0–500ms。CI4 不提供“强一致性读”语法糖,你要自己兜底。
- 关键路径(如下单后查订单)必须强制走主库读:
db_connect('default')->table('orders')->where('id', $id)->get() - 不要依赖
lastInsertId()后立刻select—— 从库可能还没同步,得用主库查 - 如果用了 MyCat 或 ShardingSphere-Proxy,可用 Hint 强制路由,例如
/*+ db_type:master */ SELECT * FROM users,但 CI4 的 Query Builder 不会自动注入这个,得用原生query()
数据清洗该在哪一层做
CI4 的 Validation 和 Filters 只负责输入校验,不处理已有脏数据;清洗(比如去重、补空值、标准化手机号)必须在业务逻辑层显式调用,不能塞进 Model 的 getter/setter 里。
- 入库前清洗:在 Controller 或 Service 层调
cleanPhone($input)、normalizeAddress($raw),再交给 Model 写库 - 出库后清洗:查完数据,用独立的
Cleaner类处理结果集,而不是在 Model 的asArray()里混逻辑 - 批量清洗别用 CI4 的 Query Builder 做:UPDATE 大表时容易锁表,应走 MySQL 原生命令或用专用 ETL 工具(如 Airflow + Python pandas)
主从配置容易卡在 CHANGE MASTER TO 的 MASTER_LOG_FILE 和 MASTER_LOG_POS 对不上,而数据清洗最容易犯的错是把清洗逻辑耦合进数据库抽象层——这两处不盯紧,上线后要么同步中断,要么脏数据越洗越乱。

















