load data会污染buffer pool,因其大批次加载使大量页被误判为热页而挤占lru新生代,导致真实热点页被淘汰;可通过会话级设置innodb_old_blocks_pct=100和innodb_old_blocks_time=0强制新页进入老年代来缓解。

为什么LOAD DATA会污染Buffer Pool?
因为LOAD DATA INFILE默认以大批次加载数据,每批页都会被逐个读入Buffer Pool并标记为“新生代页”;但这些页几乎只被访问一次(写入后就不再读),却挤占了LRU链表前端位置,导致真实热点页被快速淘汰。本质是“单次扫描型访问”被误判为“热访问”,触发了不合理的页晋升逻辑。
常见现象:SHOW ENGINE INNODB STATUS\G中看到Youngs/Scans比值骤降(比如从0.8跌到0.1),同时Pages read from disk激增,但业务查询响应变慢——说明缓存被刷得七零八落。
- 默认参数
innodb_old_blocks_pct=37和innodb_old_blocks_time=1000对LOAD DATA完全不友好:新页在1秒内就被访问多次(因连续写入),直接跳过老年代,直冲新生代顶端 -
LOAD DATA不走查询优化器路径,绕过索引统计与执行计划,Buffer Pool无法预判其访问模式,只能按通用规则处理 - 若目标表有二级索引,每行插入还额外触发索引页加载,进一步放大污染范围
如何让LOAD DATA绕开新生代晋升?
核心是强制将其访问页“钉”在老年代,避免干扰热数据。不能改全局参数(影响其他查询),而应在会话级临时调整:
SET SESSION innodb_old_blocks_pct = 100; SET SESSION innodb_old_blocks_time = 0;
这样所有新加载页一进Buffer Pool就归入老年代,且永不因短时间重复访问而晋升——它们会在后续LRU淘汰中优先被驱逐,不影响热页驻留。
- 必须用
SESSION而非GLOBAL,否则会影响整个实例的查询缓存行为 -
innodb_old_blocks_time = 0表示“只要访问一次,就视为冷页”,配合pct=100确保100%的新页都进入老年代 - 执行完
LOAD DATA后无需手动恢复,会话结束自动失效;如需复用连接,可再SET SESSION回默认值
LOAD DATA期间长锁的根本原因
不是锁本身变长,而是LOAD DATA默认在单事务中执行(除非指定LOCAL且客户端支持分片),导致整个导入过程持有一个超长事务锁。InnoDB必须维护该事务的MVCC快照,所有涉及的页都可能被标记为“脏页+未提交”,阻塞其他事务的读写。
- 现象:
SHOW PROCESSLIST里看到状态为Updating或Writing to net但Time持续增长;INFORMATION_SCHEMA.INNODB_TRX中trx_started时间远早于当前时间 - 根本限制:InnoDB的事务日志(redo log)有大小上限,大导入可能触发频繁checkpoint,拖慢刷脏速度,反过来又延长锁持有时间
- 二级索引更新是隐形锁源:即使主键有序插入,二级索引B+树分裂、页合并也会产生随机I/O和行锁等待
真正有效的分片与锁控制策略
不要依赖LINES TERMINATED BY等语法做“伪分片”,要从事务粒度切分。MySQL 8.0+支持LOAD DATA的ROWS IDENTIFIED BY,但更可靠的是用外部工具拆文件+循环导入:
- 用
split -l 10000 data.csv chunk_把大文件切为1万行/片,每片单独执行LOAD DATA - 每个导入语句前加
START TRANSACTION,后加COMMIT,显式控制事务边界 - 关键:在
LOAD DATA语句后立即执行SELECT SLEEP(0.1)(哪怕0.1秒),给后台刷脏线程留出窗口,避免redo log打满 - 禁用唯一性检查和外键校验:
SET UNIQUE_CHECKS=0; SET FOREIGN_KEY_CHECKS=0;,导入完成再恢复
这比调大innodb_log_file_size或innodb_flush_log_at_trx_commit更直接有效——锁时长由事务体积决定,不是由刷盘策略决定。
最易被忽略的一点:LOAD DATA加载后,Buffer Pool里大量页处于“脏但未刷盘”状态,此时如果立刻执行大查询,会触发大量同步刷脏(尤其是innodb_max_dirty_pages_pct接近阈值时),反而造成二次IO风暴。建议导入后执行SET GLOBAL innodb_max_dirty_pages_pct = 50;临时压低刷脏水位,等系统空闲再调回。











