mysqldump默认使用mysql_store_result,将整表结果全载入客户端内存导致oom;加--quick启用mysql_use_result流式读取,内存稳定在几mb。需配套--skip-extended-insert和--single-transaction防中断与锁表。

mysqldump 默认会把整张表结果一次性拉到本地内存再拼 SQL,不是 MySQL 服务端崩了,是客户端程序自己扛不住——1000 万行 × 平均每行 2KB,光数据就 20GB,还没算 Python 字符串开销和对象头。
mysqldump --quick 是什么,为什么必须加
--quick 强制启用流式读取(mysql_use_result),让 mysqldump 边从服务端取一行、边写一行到磁盘,内存占用稳定在几 MB 级别。
不加它,默认走 mysql_store_result 模式:服务端把全部结果集发给客户端,客户端全塞进内存再处理。
这个行为和 innodb_buffer_pool_size 无关,调大服务端缓存完全救不了客户端 OOM。
哪些配套参数能避免二次踩坑
-
--skip-extended-insert:禁用多值 INSERT(如INSERT INTO t VALUES (1),(2),(3)),防止单条语句超max_allowed_packet导致导出中断 -
--single-transaction:InnoDB 表用它替代--lock-tables,避免锁表 + 全量缓存双重加压 -
--no-autocommit --skip-extended-insert组合可进一步降低导入时的内存压力(非导出阶段,但常被一起配错)
常见错误现象和误判点
现象包括:mysqldump 进程 RSS 持续上涨、系统 swap 被大量使用、导出中途卡死或被 oom-killer 杀掉。
容易误判的是:看到 dmesg -T | grep "killed process" 里有 mysqld 就以为是 MySQL 崩了——其实日志里杀的是 mysqldump 进程本身;
另一个坑是改了 max_allowed_packet 却没加 --quick,结果只是让单包更大,但整表还是全进内存,OOM 照样发生。
流式模式下不可用的操作
启用 --quick 后,mysqldump 内部不再缓存结果集,所以不能做任何需要随机访问的行为:
— 不支持 --where 配合大偏移(如 LIMIT 1000000,100),因为无法跳过前 100 万行
— 不支持导出时动态过滤字段(需靠 --ignore-column 或应用层后处理)
— 如果导出中途失败,没法 resume,只能重来——这是流式必然代价
--quick,它依然会尝试分配一个空结果集缓冲区——而某些旧版客户端甚至会预分配固定大小(如 64MB)不管实际数据量。











