mysqldump导出内存不足主因是客户端oom或/tmp满,--quick仅优化客户端读取,对服务端内存压力、元数据加载、myisam锁表及管道阻塞无效;应优先检查df -h /tmp、df -i /tmp、lsof +l1及临时目录配置。

mysqldump 导出报内存不足,大概率不是服务端崩了,而是客户端进程被系统 OOM killer 杀掉,或 /tmp 分区写满。直接加 --quick 不一定管用,得看堆在哪。
为什么 --quick 有时没效果
它只控制客户端读取方式:默认把整张表查出来缓存在内存里再写文件;加了之后改用逐行 mysql_fetch_row(),客户端内存压到几 MB。但以下情况它救不了:
- 服务端仍在构建完整结果集(
InnoDB要维持一致性视图),innodb_buffer_pool_size配太小会导致服务端自己先扛不住 - 启用了
--routines、--events或--triggers,而库中有上百个存储过程,mysqldump会一次性拉取全部定义并拼 SQL,这部分不走流式逻辑 -
/tmp是tmpfs(内存挂载),大表导出会先落盘再压缩,/tmp满了就报 “Cannot allocate memory” —— 实际是磁盘空间不足 - MyISAM 表锁表期间无法流式输出,
--quick基本无效
真正该优先检查的三个地方
别急着调参数,先定位真实瓶颈:
- 运行
df -h /tmp和df -h(看你备份路径所在分区),再补一句df -i /tmp—— 小文件多时 inode 可能先耗尽 - 查
SELECT @@tmpdir, @@innodb_tmpdir;,确认临时文件是否真往大分区写;若不是,加--tmpdir=/data/tmp显式指定 - 执行
lsof +L1,看有没有已删未释放的大日志或临时文件占着空间(常见于长期运行的 mysqldump 卡住后被 kill)
--single-transaction 必须和 --quick 配合用
单独用 --single-transaction 不能降内存,它只是开一个一致性快照事务,避免锁表;但若不用 --quick,客户端仍会把整个快照结果缓存在内存里。两者合体才安全:
mysqldump --single-transaction --quick -u user -p db_name > dump.sql- 对
InnoDB有效;MyISAM不支持快照,此时必须用--lock-all-tables,但会阻塞写入 - 若导出含
VIEW或ROUTINE,记得额外加--skip-triggers --skip-routines --skip-events来规避元数据内存堆积
导出卡在管道里反而更危险
像 mysqldump --quick db | gzip > backup.sql.gz 这种写法,看着省空间,实则埋雷:
- 接收端(如 gzip 或网络传输)一旦卡住,TCP 窗口堵死,MySQL 服务端连接会 hang 住,拖慢甚至卡死其他查询
-
--compress不缓解此问题,还加重 CPU - 更稳的做法:先写本地磁盘(哪怕用
--tmpdir=/dev/shm内存盘),再分步压缩传输 - 非走管道不可?至少加
--max-allowed-packet=64M并确保net_buffer_length足够,减少重传压力
最常被忽略的一点:内存不足的根因往往不在 mysqldump 自身,而在它触发的副作用——比如临时表写爆 /tmp、日志文件没轮转、或者 innodb_buffer_pool_size 和系统内存严重不匹配。先查 df 和 lsof +L1,比盲目加参数有用得多。











