每批控制在400条左右最安全,这是兼顾MySQL协议限制、PHP内存占用和事务稳定性的实测阈值;具体由max_allowed_packet、PDO占位符上限、锁表风险等因素共同决定,不同场景可在200–800条间微调。

每批控制在 400 条左右最安全,这是兼顾 MySQL 协议限制、PHP 内存占用和事务稳定性的实测阈值。
为什么是 400 条?
不是凭空定的,而是由几个硬性约束共同决定的:
- MySQL
max_allowed_packet默认为 4MB,一条含中英文、时间戳、少量 JSON 的记录平均占 2–5KB,超过 1000 条就容易触顶 - TP6/TP8 的
insertAll()拼成单条 INSERT 语句,SQL 长度随数据量线性增长,400 条通常能稳控在 3MB 内 - PDO 绑定参数有上限(尤其旧版本),超 500–1000 占位符易报 “too many placeholders”
- 事务过大易锁表、回滚慢、日志暴涨;过小则频繁提交,抵消批量优势
不同场景可微调的范围
400 是通用推荐值,实际可根据环境小幅浮动:
- 字段极简(如纯 ID + 状态)、无中文、无 JSON:可试 500–600 条
- 含长文本、多 JSON 字段、UTF-8 多字节字符多:建议降到 200–300 条
- CLI 脚本 +
gc_collect_cycles()+memory_limit放宽:可上探至 800 条,但不建议突破 1000 - Web 请求(如上传 Excel 后导入):必须 ≤ 300 条,并配合队列或前端分片,避免超时断连
别依赖“自动分批”参数
虽然 Db::insertAll($data, 500) 看似支持自动切片,但它只是客户端逻辑拆分,仍会逐批开启独立 SQL 执行——无法规避单次 SQL 长度风险,也不受事务统一管控。真正安全的做法是:
立即学习“PHP免费学习笔记(深入)”;
- 用
array_chunk($data, 400)主动切片 - 每片单独调用
Db::name('table')->insertAll($chunk) - 外层用
Db::transaction()或startTrans()包裹每片(非全部)
避开两个常见误判
有人按“性能越高越好”盲目拉高批次,结果翻车;也有人因一次失败就缩到 50 条,严重拖慢整体速度。关键看两点:
- 失败是否可接受:若某批失败需重试整批,400 条比 1000 条更容易定位和恢复
- 数据是否可信:清洗过的离线数据可用 400;前端直传、未校验的数据建议 200 并加异常捕获



















