MySQL多值INSERT一次最多1000–2000行最稳妥,因受max_allowed_packet限制且避免锁持有过长;需显式关闭autocommit并合理设置隔离级别,LOAD DATA INFILE才是最快绕过SQL层锁的方案。

MySQL 多值 INSERT 一次最多塞多少行
别迷信“越多越好”。INSERT INTO t (a,b) VALUES (1,2), (3,4), ... 看似高效,但单次超过 5000 行就容易触发 max_allowed_packet 截断或内存溢出;超 10000 行还可能让 InnoDB 持有行锁时间过长,间接导致其他查询被阻塞。实测安全上限是 1000–2000 行/批,配合事务控制最稳。
为什么加了事务还是锁表?关键在 autocommit 和隔离级别
即使写了 BEGIN; INSERT ...; COMMIT;,如果客户端连接默认开启 autocommit=1,每条语句仍是独立事务,锁不会累积释放——这不是你想要的“批量”。必须显式关掉:SET autocommit = 0; 或用 START TRANSACTION。另外,REPEATABLE READ 下大事务会持有很多 gap lock,换成 READ COMMITTED 可显著减少锁范围,尤其适合只写不读的导入场景。
LOAD DATA INFILE 是绕过锁的真正捷径
这是 MySQL 原生最快、锁粒度最小的方式,它跳过 SQL 解析层,直接走存储引擎路径。但要注意三个硬条件:
-
LOCAL INFILE必须在客户端连接时启用(mysql --local-infile)且服务端local_infile=ON - 数据文件需 UTF-8 编码,字段分隔符(如
\t)和行结束符(\n)要与LOAD DATA语句严格一致 - 目标表不能有活跃的外键约束或触发器,否则退化为逐行处理
示例:LOAD DATA LOCAL INFILE '/tmp/data.csv' INTO TABLE users FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n' IGNORE 1 ROWS;
禁用索引不是万能药,得看场景
ALTER TABLE users DISABLE KEYS; 只对 MyISAM 有效,InnoDB 完全无视。InnoDB 用户想提速,只能临时删掉非必要二级索引,插入完再重建——但要注意:主键聚簇索引无法禁用,且重建索引本身也耗时、占 IO。更稳妥的做法是插入前确保数据按主键顺序排列(比如先 ORDER BY id),避免页分裂带来的随机写放大。
INSERT ... VALUES,如果批大小失控、autocommit 没关、主键无序,照样锁表。这些细节不调,光换写法只是把问题从“慢”变成“更隐蔽的慢”。

















