codeigniter批量插入需分块、事务与默认值补全,而非直接使用分页数据;否则因字段缺失、键名不匹配或无事务导致静默失败、io爆炸或数据丢失。

分页数据批量插入不是“先分页再插入”,而是分页只是前端展示手段,真正要优化的是后端导入或写入逻辑。很多开发者误把“分页加载的数据”直接拿去 insert_batch(),结果要么失败、要么丢数据、要么卡死——问题不在分页,而在批量写入方式本身。
别用分页数组直接 insert_batch()
用户翻页看到的 20 条数据,本质是 LIMIT + OFFSET 查询结果,它只适合读取展示。如果把这些结果原样传给 insert_batch():
- 字段缺失:查询可能 SELECT id,name,email,但目标表还有 created_at、status 等 NOT NULL 字段,insert_batch() 遇到 NULL 就静默失败
- 键名不匹配:数据库列是 user_id,而查询结果键是 id,CI3 自动忽略该字段,导致整行字段数不足
- 无事务保护:50 条 × 单条 auto-commit = 50 次磁盘写,IO 压力大,失败难回滚
正确做法:分块 + 事务 + 补全默认值
真正高效的批量插入,和是否分页无关,关键在数据准备和执行控制:
- 把原始数据(如 CSV、API 返回、后台上传)按 ≤ 500 条切分成块,避免 max_allowed_packet 超限
- 每块开启事务:
$this->db->transStart();,插完调$this->db->transComplete();,再检查$this->db->transStatus() - 循环前统一补默认值:
$row['created_at'] = $row['created_at'] ?? date('Y-m-d H:i:s');,防止 NULL 写 NOT NULL 字段 - 确保所有记录都是关联数组,且 key 名与数据库列名完全一致(区分大小写),可用
array_key_exists('email', $row)批量校验
重复数据?用 ON DUPLICATE KEY UPDATE 替代 insert_batch
如果是从 Excel 或外部系统同步数据,大概率存在重复主键/唯一索引冲突。insert_batch() 会直接报错中断,而原生 SQL 的 INSERT ... ON DUPLICATE KEY UPDATE 可自动跳过或更新:
- 前提:目标表必须有 PRIMARY KEY 或 UNIQUE INDEX(如 email 字段设为 UNIQUE)
- CI3 中需手拼 SQL:
$sql = "INSERT INTO users (name, email) VALUES (?, ?) ON DUPLICATE KEY UPDATE name = VALUES(name)"; - CI4 可用 query builder 绑定参数,更安全:
$this->db->query($sql, [$name, $email]); - 想纯跳过不报错?写
ON DUPLICATE KEY UPDATE id = id即可
调试必开:db_debug 和 error 检查
insert_batch() 失败不抛异常,只返回 FALSE,错误藏在 $this->db->error() 里:
- 开发期务必开启:
$this->db->db_debug = TRUE;(CI3)或.env中设database.default.DB_DEBUG = true(CI4) - 每次 insert_batch() 后加判断:
if ($this->db->affected_rows() === FALSE) { log_message('error', json_encode($this->db->error())); } - 避免只看返回值是否为 true/false,一定要查
affected_rows()或error()











