必须设batch_size,否则Django将全部实例拼成单条超长INSERT语句,触发MySQL max_allowed_packet=4MB或SQLite隐式长度限制,导致“MySQL server has gone away”等报错,并引发OOM;安全起点为500–1000,但需按字段类型(如TextField、BinaryField)压测调整,文本多时建议100–200。

bulk_create 必须设 batch_size,否则大概率崩库或 OOM——这不是性能问题,是稳定性红线。
为什么不设 batch_size 的 bulk_create 会直接失败
不传 batch_size 参数时,Django 把全部实例拼进一条 INSERT INTO ... VALUES (),(),()...,这在 MySQL 和 SQLite 上极易触发底层限制:
- MySQL 默认
max_allowed_packet=4MB,1000 条含TextField或长字符串的记录轻松超限,报错如:django.db.utils.OperationalError: (2006, "MySQL server has gone away") - SQLite 对单条 SQL 长度有隐式上限,超长直接抛
sqlite3.OperationalError - 内存占用随数据量线性增长,10 万条可能吃掉几百 MB,生产环境容易 OOM
batch_size 设多少才安全
没有万能值,必须按字段结构压测。经验起点是 500–1000,但需根据实际调整:
- 纯整数/短字符字段:可试 1000–2000
- 含
TextField、BinaryField或 JSON 字段:建议降到 100–200 - 线上部署前,用真实数据结构 + 真实字段长度跑压测(比如插入 5 万条模拟数据,观察内存峰值和错误率)
auto_now/auto_now_add 字段为空、主键缺失怎么办
bulk_create 完全绕过 Model.save(),所以:
SkillSub Pro - Python 题解与代码注释双功能技能功能概述SkillSub Pro - Python 题解与代码注释双功能技能是一项面向实际任务的技能,主要用于SkillSub Pro 是一个 Python 题解生成与代码注释的 双功能合体技能 ,专为学生、算法学习者和开发者设计;✅ 一个技能,两种用途 :;核心要点📝 题解模式 :输入题目/题号,自动生成完整 Python 题解(含详细注释、解题思路、复杂度分析);💬 注释模式 :输入 Python 代码,自动添加详细中。它将相关步骤、
立即学习“Python免费学习笔记(深入)”;
-
auto_now和auto_now_add字段不会自动填充,必须显式赋值,例如:created_at=datetime.now() - MySQL/SQLite 下
bulk_create不返回主键(book.id全为None),PostgreSQL 仅在未设batch_size时通过RETURNING返回——但你不能依赖这个,因为不设batch_size本身就不安全 - 想靠
refresh_from_db()补 ID?无效。它对bulk_create不起作用
关联表写入失败的唯一可行解
这种链式写法必然失败:
books = Book.objects.bulk_create(book_instances) chapters = [Chapter(book_id=b.id, title='') for b in books] # b.id 全为 None Chapter.objects.bulk_create(chapters)
可行路径只有两个:
- 先插主表(加
ignore_conflicts=True,确保唯一约束存在),再用Book.objects.filter(title__in=[...]).values_list('id', 'title')反查 ID,靠业务字段(如title、isbn)对齐 - 手动预分配 ID:清空表后显式设
id字段(如Book(id=i+1, title=...)),只适用于初始化、迁移等可控场景
真正容易被忽略的点是:字段类型决定 batch_size 上限,不是数据条数。100 条带图片 Base64 的记录,可能比 5000 条纯数字还危险。


















