mysqldump分块导出需用--single-transaction(InnoDB)+--skip-lock-tables、按表或主键ID分批、WHERE须命中主键索引、边dump边pigz压缩、恢复时用--force跳过运行时错误。

mysqldump 分块导出时怎么避免锁表和 OOM
超大数据库直接 mysqldump 容易卡死或触发 MySQL 的 max_allowed_packet 限制,更危险的是默认会锁表(尤其 MyISAM),InnoDB 虽支持 --single-transaction,但长事务仍可能拖慢线上查询。
- 必须加
--single-transaction(仅对 InnoDB 有效),否则备份期间写入会被阻塞 - 用
--skip-lock-tables配合--single-transaction,别单独用前者——它不解决一致性问题 - 调大客户端参数:
--max-allowed-packet=512M,同时确认服务端max_allowed_packet≥ 同值 - 分表导出比“按行分块”更可靠:用
mysql -e "SHOW TABLES LIKE 'log_%'"批量生成表名,再循环调mysqldump
按主键 ID 分批次导出大表的实操要点
单表超 10GB 且不能停写时,mysqldump --where 是唯一可行的分块方式,但极易因索引缺失、WHERE 条件扫描全表而变慢甚至夯住。
- WHERE 必须命中主键或高效索引,例如:
--where="id BETWEEN 1 AND 100000",别用created_at > '2023-01-01'(没索引就扫全表) - 每次导出后记录最大
id,下一批从id > 上次最大值开始,避免漏数据 - 加
--no-create-info --skip-triggers --skip-routines减少元数据开销 - 别用
--extended-insert=FALSE:虽然方便调试,但插入性能暴跌 5–10 倍,压缩率也差
gzip / pigz 压缩时机与内存控制
边 dump 边压缩能省磁盘空间,但默认 gzip 单线程吃满 CPU,且进程挂了整个备份就废;不压缩又占几十 GB 空间。
- 优先用
pigz替代gzip(多核并行):mysqldump ... | pigz > backup.sql.gz - 如果内存紧张(如 4GB 机器),给
pigz加-p 2限核,或改用gzip -1(最快最低压) - 严禁先写磁盘再压缩:大文件 IO + 压缩双重压力,容易触发 Linux OOM killer 杀掉 mysqld
- 校验用
gzip -t backup.sql.gz,别等恢复时才发现损坏
恢复时怎么跳过报错继续导入
分块备份后,恢复时某条 INSERT 报错(比如重复主键、字段长度超限),默认 mysql 会停在那,整批失败。
- 加
--force参数让 mysql 客户端跳过错误继续执行:zcat backup.sql.gz | mysql --force db_name - 但注意:
--force不处理语法错误,只跳过运行时错误(如 duplicate key) - 若需定位具体哪条语句失败,加
--verbose --verbose输出详细日志,配合grep -B2 -A2 "ERROR"快速定位 - 生产环境恢复前,先在测试库跑
head -n 10000 backup.sql | mysql db_test验证基础兼容性(比如字符集、SQL mode)
真正麻烦的不是命令怎么写,而是分块逻辑和业务写入节奏的耦合——比如按时间分片遇上跨天未提交的事务,或者按 ID 分片遇上批量 insert 导致主键跳跃。这些细节不会报错,但会让备份缺数据,得靠校验脚本兜底。











