每批1000~2000行是多数OLTP场景的安全起点,需据表结构、硬件及并发情况调整:字段少可试2000行/批,含TEXT/BLOB或行宽>2KB则建议500行/批,高并发优先500,离线导入可达10000但须匹配日志与缓冲池配置。

事务大小直接决定锁等待和日志压力
单次事务插入超过 5000 条,InnoDB 的 redo log 和 undo log 增长会陡增,容易触发 innodb_log_file_size 不足、事务超时或主从延迟飙升。实测中,1 万条一提交在普通 8GB 内存 MySQL 实例上,SHOW ENGINE INNODB STATUS 常报 Lock wait timeout exceeded。
- 锁持有时间随事务内行数近似线性增长,尤其有唯一索引冲突时,可能升级为间隙锁甚至表级锁
-
max_allowed_packet限制了单条 SQL 最大长度,间接约束了INSERT ... VALUES (...),(...)能塞多少行 - 事务越大,崩溃恢复耗时越长;若中途失败,回滚代价也越高
每批 1000~2000 行是多数 OLTP 场景的安全起点
这不是魔法数字,而是平衡网络往返、内存占用、锁粒度和日志刷盘频率后的经验值。你得根据实际表结构和硬件调。
- 字段少(如仅 2–3 个
VARCHAR(50)+INT)、无大文本:可试2000行/批 - 含
TEXT或BLOB、或行宽 > 2KB:建议压到500行/批,避免内存溢出 - 高并发写入场景(如实时日志归集):优先选
500,哪怕多几次COMMIT,也比阻塞其他业务强 - 离线导入(夜间 ETL):可拉到
10000,但必须同步确认innodb_log_file_size≥ 2GB 且innodb_buffer_pool_size≥ 4GB
用 executemany + 手动分批,别依赖自动提交
Python 的 MySQLdb 或 pymysql 默认开启 autocommit=True,逐条插入等于每条都开事务——性能崩盘。必须关掉并自己控批。
- 先执行
conn.autocommit(False)或建连时指定autocommit=False - 数据列表按目标批次切片:
[data[i:i+2000] for i in range(0, len(data), 2000)] - 每批调用一次
cursor.executemany(sql, batch),再conn.commit() - 别用
INSERT ... SELECT或LOAD DATA INFILE替代——它们虽快,但绕过应用层校验,出错难定位
容易被忽略的硬性限制:max_allowed_packet 和日志配置
就算逻辑上分了 2000 行一批,如果单行太大或字符集导致实际 SQL 超过 max_allowed_packet(默认 4MB),executemany 会直接抛 PacketTooLargeError,而不是静默截断。
- 查当前值:
SHOW VARIABLES LIKE 'max_allowed_packet'; - 临时调大(需 SUPER 权限):
SET SESSION max_allowed_packet = 1024*1024*64;(64MB) - 真正要改永久值,得在
my.cnf加max_allowed_packet = 64M并重启 - 同时检查
innodb_log_file_size:若设为 256MB,单事务写入日志不宜长期超过 128MB,对应行数就得按实际日志生成量反推
innodb_row_lock_time_avg 和 Slow_queries 是否突增。

















