mysql批量插入最直接方式是insert into ... values ( ),( ),单语句插入多行可提速约10倍;需注意括号逗号格式、max_allowed_packet限制(建议≤1000行)、null不加引号、避免sql注入,并配合事务关闭autocommit以提升性能。

INSERT INTO ... VALUES 多值语法是最直接的批量插入方式
MySQL 原生支持单条 INSERT 语句插入多行数据,这是最常用、开销最小的批量插入手段。它比循环执行多条 INSERT 语句快一个数量级,因为只经历一次 SQL 解析、一次事务日志写入(默认 autocommit 下仍可优化)。
常见错误是拼接 SQL 时漏掉括号或逗号,导致 SQL syntax error near '1,2' 类报错;更隐蔽的问题是单次插入行数过多,触发 max_allowed_packet 限制,表现为连接被服务端强制关闭或 Packets larger than max_allowed_packet are not allowed 错误。
- 单次建议控制在 1000 行以内(具体取决于字段长度和
max_allowed_packet设置,可通过SHOW VARIABLES LIKE 'max_allowed_packet'查看) - 所有值必须用圆括号包裹,每组之间用逗号分隔:
INSERT INTO t(a,b) VALUES (1,'x'),(2,'y'),(3,'z'); - 避免在 VALUES 中混用 NULL 和字符串
'NULL'—— 后者是字符,不是空值
使用 LOAD DATA INFILE 导入大文件时要注意权限与路径
当插入数据来自 CSV 或制表符分隔文件且量级达十万级以上时,LOAD DATA INFILE 比任何 INSERT 都快,但它受限于 MySQL 服务端文件系统权限,不是客户端路径。
典型错误是误把本地文件路径(如 C:\data.csv)直接写进语句,结果报错 ERROR 29 (HY000): File 'C:\data.csv' not found —— MySQL 只认服务端能访问的路径,且要求用户有 FILE 权限。
- 文件必须放在 MySQL 服务进程有读取权限的目录下(如
/var/lib/mysql-files/),或启用local_infile=ON并用LOAD DATA LOCAL INFILE -
FIELDS TERMINATED BY ','和LINES TERMINATED BY '\n'必须严格匹配文件实际格式,Windows 换行符是\r\n - 目标表需提前建好,字段顺序与文件列顺序一致;可用
SET col_name = NULLIF(@col_name, '')处理空字符串转 NULL
INSERT IGNORE / ON DUPLICATE KEY UPDATE 应对重复键冲突
批量插入常遇到主键或唯一索引冲突,INSERT IGNORE 会跳过冲突行,而 ON DUPLICATE KEY UPDATE 允许指定冲突后更新哪些字段——二者语义完全不同,选错会导致数据丢失或覆盖错误。
比如用 INSERT IGNORE 插入含时间戳的记录,若已有旧数据,新数据不会进库也不报错,业务上可能以为成功了;而 ON DUPLICATE KEY UPDATE updated_at = NOW() 才是更新场景该用的。
-
INSERT IGNORE对所有约束冲突都静默忽略(包括外键),不推荐用于关键业务逻辑 -
ON DUPLICATE KEY UPDATE只响应主键/唯一键冲突,其他错误(如数据类型不符)仍会报错 - 更新子句中不能引用未在 INSERT 列表中出现的列,否则报错
Unknown column 'x' in 'field list'
批量插入性能受 autocommit 和索引影响极大
默认开启 autocommit 时,每条 INSERT 都是一次事务提交,磁盘 I/O 成为瓶颈。关闭它并手动 COMMIT,配合合理索引策略,能提升 5–10 倍吞吐。
容易被忽略的是:即使关了 autocommit,如果表上有多个二级索引,每插入一行仍要更新所有索引树——此时批量插入的收益会被稀释。某些场景下,先 DROP INDEX,插完再 CREATE INDEX 反而更快。
- 执行前加
SET autocommit = 0;,最后COMMIT;;或用事务块BEGIN; ... ; COMMIT; - 大批量导入前可临时禁用唯一性检查:
SET unique_checks = 0;(记得之后设回 1) - 确认
innodb_buffer_pool_size足够大,避免频繁刷脏页拖慢速度











