答案:确认oom需三步证据链——dmesg查kill记录、processlist看卡顿状态、performance_schema查sp_head::main_mem_root内存飙升;备份前须禁用performance_schema、降低table_open_cache_instances和max_connections;避免sp_head溢出应分页导出、调低tmp_table_size至64mb并流式重定向。

备份进程中断不是备份工具出错,而是 MySQL 在内存不足时拒绝分配新内存——mysqldump 或 mysqlpump 一发起大查询,sp_head::main_mem_root 就开始疯涨,触发 OOM Killer 杀掉 mysqld,备份自然断在半路。
怎么确认是内存溢出而非磁盘满或权限问题
别急着重跑备份,先看证据链:
- 运行
dmesg -T | grep -i "killed process",输出含Out of memory: Kill process mysqld且时间与备份中断时刻差在 1 分钟内 → 坐实 OOM - 查
SHOW PROCESSLIST,若备份线程状态卡在executing或Sending data,且对应 SQL 是SELECT ... FROM large_table→ 很可能正拉大结果集 - 执行
SELECT EVENT_NAME, CURRENT_NUMBER_OF_BYTES_USED FROM performance_schema.memory_summary_global_by_event_name WHERE EVENT_NAME = 'memory/sql/sp_head::main_mem_root',值 >800MB 且持续上涨 → 真凶锁定
备份前必须关掉的三项内存放大器
这些配置在备份期间会把内存消耗推到临界点,必须临时禁用:
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
-
SET GLOBAL performance_schema = OFF:立即释放已累积的 performance_schema 内存(重启失效,但能救急) -
SET GLOBAL table_open_cache_instances = 1:默认 16 会让每个实例缓存一份存储过程/函数结构,直接砍掉 15/16 内存占用 -
SET GLOBAL max_connections = 50:备份通常只用 1–2 连接,高并发连接池反而吃光 free memory
mysqldump 备份时如何避免 sp_head::main_mem_root 溢出
核心是不让单次 FETCH 吃掉整张表。以下参数组合比调大 innodb_buffer_pool_size 更有效:
- 加
--single-transaction(InnoDB 表必备),但必须配合--skip-opt --no-autocommit,否则事务内仍会累积内存 - 强制分页导出:
mysqldump --where="id BETWEEN 1 AND 10000" db table,再循环跑偏移,而不是全表SELECT * - 禁用字段自动补全:
mysqldump --skip-extended-insert,避免单行 INSERT 语句过长撑爆解析内存 - 不加
--lock-tables(MyISAM 场景除外),表级锁会延长事务时间,加剧内存驻留
真正该盯的不是 innodb_buffer_pool_size,而是 tmp_table_size
备份时大量 CREATE TEMPORARY TABLE 和排序操作,tmp_table_size 和 max_heap_table_size 设太高会直接压垮 RSS:
- 查当前值:
SELECT @@tmp_table_size, @@max_heap_table_size - 临时调低(仅备份期间):
SET GLOBAL tmp_table_size = 64*1024*1024; SET GLOBAL max_heap_table_size = 64*1024*1024 - 注意:这两个值必须相等,否则 MySQL 会取小值;设 64MB 足够应付绝大多数备份场景,设 256MB+ 反而容易触发 OOM
最易被忽略的一点:备份脚本自身也吃内存。Python 的 subprocess.Popen 或 Shell 的 $(mysqldump ...) 会把整个 dump 输出缓存在内存里——务必用流式重定向,比如 mysqldump ... > backup.sql,而不是 output=$(mysqldump ...)。










