多线程不能加速单个load data infile操作,因其本质是服务端单线程执行、独占文件读取并加表级锁;必须拆分数据、隔离连接、规避锁竞争才能实现并发吞吐提升。

多线程本身不能直接加速单个 LOAD DATA INFILE 操作,但能显著提升整体吞吐——前提是拆分数据、隔离连接、规避锁竞争。
为什么不能对单个 LOAD DATA INFILE 开多线程
MySQL 的 LOAD DATA INFILE 是单线程命令,它由服务端直接读取本地文件并写入引擎,不走 SQL 解析层。你无法用多个线程“并发执行同一个 LOAD DATA INFILE 语句”去导入同一份文件——会触发表级锁(InnoDB 表在导入时加 INSERT_METHOD=NO 级别锁),且文件被独占读取,线程间还会争抢磁盘 I/O 和 buffer pool。
常见错误现象:ERROR 1086 (HY000): File 'xxx.csv' already in use 或长时间卡在 Writing to net 状态。
- 每个线程必须操作独立的数据子集(如按行号切分 CSV)
- 每个线程需使用独立数据库连接,避免连接复用导致事务/状态污染
- 目标表若含唯一索引或外键,多线程并发写入极易触发
Duplicate entry或死锁
mysqlimport 并行导入的正确姿势
mysqlimport 是 LOAD DATA INFILE 的命令行封装,天然支持多文件并行。它的性能优势来自绕过网络、跳过 SQL 解析,但必须满足:数据文件在 MySQL 服务器本地,且用户有 FILE 权限。
实操建议:
- 将原始大 CSV 拆成多个等大小文件(如每 50 万行一个),用
split -l 500000 data.csv chunk_ - 确保每个 chunk 文件字段格式一致,且不含 BOM 头;首行是标题时,所有 chunk 都要跳过(
--ignore-lines=1) - 启动多个
mysqlimport进程,各自指定不同 chunk 文件和目标表名(或同一表但加--local避免权限问题) - 关键参数必须统一:
--fields-terminated-by=',' --fields-enclosed-by='"' --lines-terminated-by='\n' - 禁用索引可提速 3–5 倍:
ALTER TABLE your_table DISABLE KEYS;导入完再ENABLE KEYS;
示例命令:
mysqlimport --user=root --password=xxx --local --fields-terminated-by=',' --fields-enclosed-by='"' --lines-terminated-by='\n' --ignore-lines=1 test_db chunk_01.csv
应用层多线程 + rewriteBatchedStatements=true
当数据源在客户端(如 Python 脚本读取远程 CSV)、无法上传到 MySQL 服务器时,这是最可控的方案。核心不是“开很多线程插很多行”,而是每个线程内用批处理 + JDBC 优化参数压缩交互开销。
关键配置与避坑点:
- JDBC URL 必须启用重写:
?rewriteBatchedStatements=true&useServerPrepStmts=false,否则addBatch()仍被拆成单条执行 - 每批次控制在 1000–5000 行之间;过小则网络往返多,过大易 OOM 或触发
max_allowed_packet限制 - 每个线程独占
Connection和PreparedStatement,禁止跨线程共享 - 关闭自动提交:
conn.setAutoCommit(false),显式commit()一次提交整批 - 避免在循环中调用
setString(i, null),应改用setNull(i, Types.VARCHAR),否则抛NullPointerException
错误日志典型提示:Communications link failure(连接超时)或 Packets larger than max_allowed_packet(未调大该参数)。
容易被忽略的系统级瓶颈
即使代码和 SQL 全部优化到位,线程数盲目增加反而会拖慢速度。真正卡住的常是这几处:
-
innodb_buffer_pool_size过小:导入时大量页缺失,频繁刷盘;建议设为物理内存的 60%–75% -
sync_binlog=1和innodb_flush_log_at_trx_commit=1:强一致性保障,但每事务都刷盘;批量导入时可临时改为0和2(重启后记得改回) -
secure_file_priv非空且路径受限:导致LOAD DATA INFILE报错ERROR 1290 (HY000),必须把文件放到指定目录下 - 磁盘类型:机械硬盘上并发线程 > 4 后基本无收益;SSD 上建议线程数 ≤ CPU 核心数 × 2
最终效果取决于最慢的一环——不是你开了几个线程,而是磁盘能否跟上、buffer pool 是否够大、日志刷盘是否被强制同步。











