备份工具横评
mariabackup / Percona XtraBackup / mydumper / clone plugin——吞吐、增量、恢复速度对比
选谁?快速决策
| 场景 | 推荐 |
|---|---|
| 单机 MariaDB 11.x | mariabackup(官方,免费) |
| 多线程逻辑备份(小库) | mydumper / myloader |
| MySQL 8 兼容(一份工具两边用) | Percona XtraBackup(兼容性最好) |
| 云上托管 | 用云厂商内置 + 异地副本 |
mariabackup
MariaDB 官方物理备份工具,fork 自 Percona XtraBackup。
# 全量
mariabackup --backup \
--target-dir=/data/backup/$(date +%F) \
--user=backup --password=xxx \
--parallel=4
# 增量(基于上次全量)
mariabackup --backup \
--target-dir=/data/backup/inc1 \
--incremental-basedir=/data/backup/2026-05-18 \
--user=backup --password=xxx
# 准备(prepare)
mariabackup --prepare --target-dir=/data/backup/2026-05-18
# 应用增量
mariabackup --prepare --apply-log-only \
--target-dir=/data/backup/2026-05-18 \
--incremental-dir=/data/backup/inc1
# 恢复
systemctl stop mariadb
rm -rf /var/lib/mysql/*
mariabackup --copy-back --target-dir=/data/backup/2026-05-18
chown -R mysql:mysql /var/lib/mysql
systemctl start mariadb
mariadb-upgrade -uroot -p性能
| 库大小 | 全量备份耗时 | 恢复耗时 |
|---|---|---|
| 10 GB | ~30s | ~30s |
| 100 GB | ~5 min | ~5 min |
| 1 TB | ~50 min | ~50 min |
| 10 TB | 数小时 | 数小时 |
线速度受 IO 限制——本地 NVMe ≈ 网络带宽峰值。
优劣
✅ 热备份不锁库 ✅ 物理拷贝速度快 ✅ 支持增量 ✅ 与 MariaDB 完全兼容
❌ 二进制格式只能 restore 到相同大版本(11.4 → 11.4,不能跨大版本) ❌ 需要服务端文件系统访问
Percona XtraBackup
MySQL 兼容版本。
xtrabackup --backup --target-dir=/data/bk
xtrabackup --prepare --target-dir=/data/bk
xtrabackup --copy-back --target-dir=/data/bk跟 mariabackup 几乎一样。MariaDB 11+ 建议用 mariabackup——XtraBackup 对新版本兼容滞后。
mydumper / myloader
多线程逻辑备份。比 mariadb-dump 快 5–10 倍。
# 备份
mydumper -h host -u backup -p xxx \
-B app \
-o /data/dump \
--threads 8 \
--compress \
--rows 1000000 # 大表自动拆段
# 恢复
myloader -h target -u root -p xxx \
-B app \
-d /data/dump \
--threads 8优劣
✅ 跨大版本可用(输出是 SQL) ✅ 跨平台、跨架构 ✅ 多线程 ✅ 支持单表 / 单库恢复
❌ 比物理备份慢 ❌ 大表恢复慢(要重建索引) ❌ 备份期间需要 consistent snapshot(短暂锁)
适合:跨版本迁移、小到中型库(< 500 GB)。
mariadb-dump(mysqldump)
mariadb-dump --single-transaction \
--routines --triggers --events \
--all-databases -uroot -p | gzip > full.sql.gz✅ 简单、随处可用 ❌ 慢、单线程 ❌ 大库不实际
只用作快速 ad-hoc 备份或小库。
clone plugin
MariaDB 没有官方 clone plugin(MySQL 8 有)。
MySQL 8 的 CLONE INSTANCE FROM ... 在 MariaDB 不存在。要用 mariabackup 或 mydumper。
备份策略实战
"三个一"原则
- 1 份本地
- 1 份异地
- 1 次真实演练过的备份
典型策略
| 频率 | 工具 | 保留 |
|---|---|---|
| 每天 0 点全量 | mariabackup | 7 天 |
| 每小时增量 | mariabackup --incremental | 24 小时 |
| Binlog 实时归档 | mysqlbinlog --read-from-remote-server --raw | 7 天 |
| 每周一次跨 region | rsync / aws s3 cp | 30 天 |
| 每月一次离线归档 | tar 到磁带 / Glacier | 1 年 |
PITR(时间点恢复)
NOW
全量备份(T0) ---------- 增量(T1) ---- 增量(T2) ---- binlog ----
|
想恢复到这里步骤:
# 1. 恢复最近的全量
mariabackup --copy-back --target-dir=T0
# 2. 应用增量
mariabackup --prepare --apply-log-only --target-dir=T0 --incremental-dir=T1
mariabackup --prepare --target-dir=T0 --incremental-dir=T2
# 3. 应用 binlog 到指定时间
mysqlbinlog --start-position=... --stop-datetime='2026-05-18 14:30:00' \
binlog.000001 binlog.000002 | mariadb -uroot -p备份验证
真演练才算有效:
# 每周一次:恢复到独立环境,跑 checksum
mariabackup --prepare --target-dir=/restore
# 启动隔离实例
docker run -d --name verify -v /restore:/var/lib/mysql:ro mariadb:11.4
# 跑业务级 health check
mysql -h verify -e "SELECT COUNT(*) FROM users;"云上托管:用云厂商提供的 restore 功能恢复到临时实例,跑 checksum。
备份的常见坑
- dump 时没加
--single-transaction→ 数据不一致 - binlog 没归档 → PITR 失败
- 备份账号权限过大 → 安全风险
- 备份带在线上的 readonly 副本上做 → 反正最常踩坑:副本延迟使备份不是想要的时间点
- 不验证 restore → 事到临头才发现备份坏了
- 同实例同地保留所有备份 → 一着火全完
- 备份不加密 → 数据泄露
- 保留期没设上限 → S3 账单暴增
自动化备份脚本
#!/bin/bash
set -euo pipefail
BACKUP_DIR=/data/backup/$(date +%Y-%m-%d)
S3_BUCKET=s3://my-backups
RETENTION_DAYS=30
mkdir -p $BACKUP_DIR
mariabackup --backup \
--target-dir=$BACKUP_DIR \
--user=backup --password="$MYSQL_PWD" \
--parallel=4
mariabackup --prepare --target-dir=$BACKUP_DIR
# 加密并上传
tar cz $BACKUP_DIR | openssl enc -aes-256-cbc -salt -k "$BACKUP_PASS" | \
aws s3 cp - $S3_BUCKET/$(basename $BACKUP_DIR).tar.gz.enc
# 清理本地
find /data/backup -mindepth 1 -maxdepth 1 -type d -mtime +7 -exec rm -rf {} +
# 清理 S3
aws s3 ls $S3_BUCKET/ | awk '{print $4}' | while read key; do
ts=$(echo $key | sed 's/\.tar.gz.enc//')
if [[ $(date -d "$ts" +%s) -lt $(date -d "$RETENTION_DAYS days ago" +%s) ]]; then
aws s3 rm $S3_BUCKET/$key
fi
done