应分表导出并压缩:用mysqldump按表单独导出+ pigz压缩,或改用xtrabackup --stream=xbstream | pigz生成无大小限制的xbstream.gz文件。

备份文件超过4GB时无法写入NTFS/FAT32分区
Windows下默认FAT32分区单文件上限为4GB,而mysqldump导出的SQL文本、尤其是含BLOB或长文本的库,极易突破该限制。这不是MySQL问题,而是文件系统硬限制——哪怕磁盘剩余空间充足,write()系统调用也会直接返回EFBIG错误。
解决思路不是“绕过限制”,而是从源头避免生成超大单文件:
- 用
mysqldump --skip-extended-insert反而会让文件更大(每行INSERT都带完整语句),必须保留--extended-insert(默认开启)以压缩SQL体积 - 强制分表导出:
mysql -e "SHOW TABLES FROM your_db" | tail -n +2 | xargs -I{} mysqldump -u user -p your_db {} | pigz > {}.sql.gz,每个表独立压缩,天然规避单文件超限 - 若必须合并成一个逻辑备份,改用
xbstream流式打包:xtrabackup --backup --stream=xbstream . | pigz > full.xbstream.gz,xbstream格式无单文件大小限制,且支持后续解包还原
mysqldump导出时触发“Out of memory”或卡死
当单表行数超千万、字段含TEXT/BLOB时,mysqldump默认把整张表加载进内存再拼SQL,极易OOM或长时间无响应。这不是配置max_allowed_packet能解决的——那是针对网络传输的,dump进程本身不受其约束。
关键控制点在查询粒度和缓冲行为:
- 对大表必须加
--single-transaction(InnoDB)或--lock-tables=false(MyISAM),否则全表锁会阻塞业务 - 禁用
--opt(它隐含--add-drop-table等,增加内存开销),显式指定精简参数:mysqldump -u u -p --no-autocommit --skip-triggers --compact your_db table_name - 用
--where分批导出:例如按时间切片--where="created_at >= '2025-01-01' AND created_at ,配合脚本循环生成季度备份
gzip压缩后仍超存储配额,但又不能删数据
单纯换gzip为pigz只能提升3–5倍速度,压缩率改善有限。真正减体积要动数据结构本身:
- 导出前执行
OPTIMIZE TABLE对已删除行做空间回收(注意:该操作会锁表,建议在低峰期+从库执行) - 用
--ignore-table=db.audit_log跳过纯日志表;用--no-create-info省掉CREATE语句(若已有建表脚本) - 对JSON/TEXT字段,若业务允许,导出前临时脱敏或截断:
UPDATE sensitive_table SET payload = LEFT(payload, 1000) WHERE LENGTH(payload) > 1000
备份后校验失败或恢复报错“Unknown command”
常见于用mysqldump导出时混用了不兼容的MySQL版本特性(如8.0的JSON_TABLE函数),或压缩过程中损坏。重点检查两处:
- 导出时加
--set-gtid-purged=OFF(若不用GTID)或--set-gtid-purged=AUTO(若用),避免GTID语句污染SQL文件 - 校验必须用
pigz -t backup.sql.gz而非gzip -t,因pigz生成的gzip流可能被旧版gzip拒绝 - 恢复前先抽样检查头尾:
zcat backup.sql.gz | head -20看是否有CREATE DATABASE,zcat backup.sql.gz | tail -10看是否以UNLOCK TABLES或COMMIT结尾
xtrabackup物理备份+binlog,后者才考虑mysqldump分块压缩。选错路径,后面所有优化都是在给错误方案打补丁。


















