codeigniter 3 和 4 的批量插入需配合事务、分块及 strict mode 调整才真正高效;ci3 的 insert_batch() 本质是 n 次单条 insert 串行执行,受 max_allowed_packet 限制,字段含关键字须手动加反引号,返回总影响行数或 false,错误藏于 $this->db->error();ci4 的 insertbatch() 默认逐条预处理,不包事务则性能无提升;strict mode 不关会导致空字符串插非空字段等整批失败,必须显式禁用;手拼多值 insert 虽快但需自行处理 null、字符集、转义与注入风险。

CodeIgniter 3 和 4 的批量插入不是“一键提速”,而是必须配合事务、分块和 strict mode 调整才能真正生效;不处理这些,insert_batch() 或 insertBatch() 只是把慢操作从循环里搬进框架里,本质没变。
CI3 的 insert_batch() 为什么插着插着就报错?
它根本不是单条多值 INSERT,而是把二维数组拆成 N 次 insert() 串行执行。所以:
- 遇到 MySQL 的
max_allowed_packet限制时照样失败——数据量大了,拼出来的 SQL 字符串超长,直接被服务端拒收 - 字段名含关键字(如
order、group)必须手动加反引号:数组键得写成'`order`' => 'desc',用field_bind()完全无效 - 返回值是总影响行数(int),不是布尔值;失败时只返回
FALSE,错误细节藏在$this->db->error()里,不查就以为是超时 - 默认每条都 auto-commit,500 条 = 500 次磁盘刷写,IO 爆炸
CI4 的 insertBatch() 默认并不快
它用了预处理(安全性提升),但默认仍是逐条执行 INSERT,没开事务、没关 auto-commit,性能跟 CI3 差不多。真正提速靠的是人工干预:
- 必须显式包事务:
$this->db->transStart(); $this->db->table('users')->insertBatch($data); $this->db->transComplete(); - 分块大小建议 ≤ 500 行:再大容易触发 MySQL 的
wait_timeout或连接中断 - 有自增主键时,只返回第一条生成的 ID —— 别拿它去关联后续逻辑
- 若表结构含非空字段但传了空字符串,strict mode 一开整批失败,错误提示极不友好
strict mode 不关,批量插入就是定时炸弹
MySQL 默认开启 strict mode,遇到空字符串插 NOT NULL 字段、非法时间格式等,整批直接中止,且不告诉你哪条出问题。
- CI3:在数据库配置数组里加
'stricton' => FALSE,或连接后执行$this->db->query('SET sql_mode = ""'); - CI4:在
.env中修改 DSN,加上strict=0,例如:database.default.DSN="mysql:host=localhost;dbname=test;charset=utf8mb4;strict=0" - 务必确认没调过
$this->db->transOff(),否则事务开关失效,白包
想真·快?只能手拼多值 INSERT,但风险自担
CI 查询构建器不提供原生多值语法支持(INSERT INTO t VALUES (),(),()),要自己拼。这时最常翻车的不是语法,是:
-
NULL值处理:PHPnull直接拼进 SQL 会变成字符串'null',得判空后写成不带引号的NULL - 中文乱码:字符集没设对(比如连的是
utf8而非utf8mb4),或 PHP 字符串本身编码不对,插入后变问号或截断 - 字段名/值未转义:尤其用户输入进来的字段名含空格或关键字,不加反引号必报错
- 没有绑定参数:SQL 注入风险回归,别图快绕过安全层
事务、分块、strict mode 这三件事,漏掉任何一项,批量插入的“高效”就只是幻觉。尤其是 strict mode,90% 的莫名失败都栽在这上面,但它又最容易被忽略。











