运维管理27 分钟阅读
数据库备份工具终极对比:MySQL 篇(XtraBackup vs mysqldump vs mydumper)+ PostgreSQL 篇(Barman vs pgBackRest)
备份是 DBA 的生命线,选对工具事半功倍。本文分 MySQL 和 PostgreSQL 两大阵营,深度对比 5 款主流备份工具的原理、性能、适用场景,并给出生产环境的备份策略建议。
2026年5月6日阅读—点赞—收藏—
mysqlpostgresql
在知识库中专注阅读,并随时返回相关工具与课程
备份是 DBA 的生命线,选对工具事半功倍。本文分 MySQL 和 PostgreSQL 两大阵营,深度对比 5 款主流备份工具的原理、性能、适用场景,并给出生产环境的备份策略建议。
做 DBA 这么多年,我见过太多"事后诸葛亮"的案例了。数据库跑得好好的,突然有一天磁盘坏了、误操作删了表、甚至遇到勒索病毒,这时候你才发现——备份要么没做,要么做了但恢复不了。
所以我一直跟团队讲:备份是 DBA 的生命线,恢复演练才是真正的保险单。
今天这篇文章,我把 MySQL 和 PostgreSQL 两大阵营的主流备份工具拉出来做一次全面对比。不搞那种泛泛而谈的科普,直接上原理、上命令、上生产配置。希望你看完之后,能根据自己的业务场景选出最合适的工具。
我们要对比的工具一共 5 款:
本章目标:掌握本章核心知识点 前置要求:完成前序章节学习 预计时长:60 分钟
mysqldump 是 MySQL 自带的逻辑备份工具,原理非常直白:连接数据库,把数据导出为 SQL 语句。备份文件就是一堆 CREATE TABLE 和 INSERT INTO,纯文本,人眼可读。
它的执行流程大致如下:
SELECT 查询逐行读取数据最基础的全库备份:
1mysqldump -u root -p --all-databases > full_backup.sql生产环境推荐的参数组合:
1mysqldump -u root -p \2 --single-transaction \3 --routines \4 --triggers \5 --events \6 --set-gtid-purged=OFF \7 --quick \8 --max-allowed-packet=512M \9 --databases mydb1 mydb2 \10 | gzip > /backup/mysql_$(date +%Y%m%d_%H%M%S).sql.gz几个关键参数解释一下:
--single-transaction:使用 InnoDB 的一致性快照,备份期间不锁表,这个参数对 InnoDB 来说是必须的--routines:导出存储过程和函数,默认不导出,很多人踩坑就在这里--triggers:导出触发器(默认开启,但显式写上更安全)--events:导出事件调度器--quick:逐行读取而不是一次性加载到内存,大表必备--set-gtid-purged=OFF:避免 GTID 相关的恢复问题,尤其是跨集群迁移时单表备份:
1mysqldump -u root -p --single-transaction mydb users > users_backup.sql恢复操作:
1# 直接恢复2mysql -u root -p < full_backup.sql34# 恢复压缩文件5gunzip < /backup/mysql_20260506.sql.gz | mysql -u root -p67# 恢复到指定数据库8mysql -u root -p target_db < users_backup.sql优点:
缺点:
--quick 的话,大表会撑爆内存--single-transaction 不起作用,会锁全库mydumper 是一个开源的 MySQL 多线程备份工具,核心思路是:把 mysqldump 的单线程变成多线程。
它的工作方式是:
FLUSH TABLES WITH READ LOCK + START TRANSACTION WITH CONSISTENT SNAPSHOT)恢复工具 myloader 同样支持多线程并行导入。
1# Ubuntu / Debian2apt-get install mydumper34# CentOS / RHEL5yum install https://github.com/mydumper/mydumper/releases/download/v0.16.3/mydumper-0.16.3-1.el8.x86_64.rpm67# 从源码编译8git clone https://github.com/mydumper/mydumper.git9cd mydumper && mkdir build && cd build10cmake ..11make && make install多线程全库备份:
1mydumper \2 -u root -p 'password' \3 -h 127.0.0.1 \4 -t 8 \5 --compress \6 --rows 100000 \7 --trx-consistency-only \8 -o /backup/mydumper_$(date +%Y%m%d)参数说明:
-t 8:使用 8 个线程并行导出--compress:输出文件使用 gzip 压缩--rows 100000:每 10 万行切分为一个 chunk 文件,方便并行恢复--trx-consistency-only:只对 InnoDB 使用事务一致性,减少锁持有时间备份输出的目录结构:
mydumper 备份目录中的元数据、表结构与数据分片
多线程恢复:
1myloader \2 -u root -p 'password' \3 -h 127.0.0.1 \4 -t 8 \5 --overwrite-tables \6 -d /backup/mydumper_20260506我在一台 16 核 64GB 的机器上做过实测,备份一个 200GB 的 MySQL 数据库:
备份速度提升约 5-7 倍,恢复速度提升约 5-8 倍,效果非常显著。
优点:
缺点:
Percona XtraBackup 是一款开源的 MySQL 物理备份工具。它的核心原理是:直接拷贝 InnoDB 的数据文件,同时追踪 redo log 的变化。
和逻辑备份不同,物理备份不需要执行 SQL 查询,而是直接操作底层文件:
.ibd 文件)FLUSH TABLES WITH READ LOCK(极短时间)关键点在于:InnoDB 数据文件的拷贝过程完全不需要锁表,因为 redo log 会记录拷贝期间的所有变化,后续 prepare 阶段会通过重放 redo log 让数据达到一致状态。
1# Ubuntu / Debian2wget https://repo.percona.com/apt/percona-release_latest.generic_all.deb3dpkg -i percona-release_latest.generic_all.deb4percona-release enable-only tools release5apt-get update && apt-get install percona-xtrabackup-8067# CentOS / RHEL8yum install https://repo.percona.com/yum/percona-release-latest.noarch.rpm9percona-release enable-only tools release10yum install percona-xtrabackup-80注意
注意:XtraBackup 8.0 适用于 MySQL 8.0,XtraBackup 2.4 适用于 MySQL 5.7,不可混用。
第一步:执行全量备份
1xtrabackup --backup \2 --user=root --password='yourpassword' \3 --target-dir=/backup/full/$(date +%Y%m%d) \4 --parallel=4 \5 --compress \6 --compress-threads=4第二步:Prepare(准备恢复)
备份完成后,数据文件可能处于不一致状态(因为备份期间有写入),需要通过 prepare 步骤重放 redo log:
1# 先解压(如果使用了 --compress)2xtrabackup --decompress --target-dir=/backup/full/2026050634# Prepare:重放 redo log,使数据达到一致状态5xtrabackup --prepare --target-dir=/backup/full/20260506第三步:恢复
1# 停止 MySQL2systemctl stop mysqld34# 清空数据目录5rm -rf /var/lib/mysql/*67# 拷贝备份文件到数据目录8xtrabackup --copy-back --target-dir=/backup/full/20260506910# 修复权限11chown -R mysql:mysql /var/lib/mysql1213# 启动 MySQL14systemctl start mysqldXtraBackup 最强大的特性之一就是增量备份。它只备份自上次备份以来变化的数据页,大幅节省时间和空间。
周日:全量备份
1xtrabackup --backup \2 --user=root --password='yourpassword' \3 --target-dir=/backup/full/sunday周一到周六:增量备份
1# 周一增量(基于周日全量)2xtrabackup --backup \3 --user=root --password='yourpassword' \4 --target-dir=/backup/inc/monday \5 --incremental-basedir=/backup/full/sunday67# 周二增量(基于周一增量)8xtrabackup --backup \9 --user=root --password='yourpassword' \10 --target-dir=/backup/inc/tuesday \11 --incremental-basedir=/backup/inc/monday恢复增量备份:
1# 1. Prepare 全量(注意 --apply-log-only,不要回滚未提交事务)2xtrabackup --prepare --apply-log-only --target-dir=/backup/full/sunday34# 2. 合并周一增量5xtrabackup --prepare --apply-log-only \6 --target-dir=/backup/full/sunday \7 --incremental-dir=/backup/inc/monday89# 3. 合并周二增量(最后一个不需要 --apply-log-only)10xtrabackup --prepare \11 --target-dir=/backup/full/sunday \12 --incremental-dir=/backup/inc/tuesday1314# 4. 恢复(同全量恢复步骤)15xtrabackup --copy-back --target-dir=/backup/full/sunday优点:
缺点:
一句话选型建议:
PostgreSQL 的备份生态和 MySQL 有很大不同。PG 原生提供了 pg_dump 和 pg_basebackup,但在企业级场景下,大家更多使用 Barman 和 pgBackRest 这两个专业工具。
Barman(Backup and Recovery Manager)是 2ndQuadrant(现已被 EDB 收购)开发的 PostgreSQL 备份管理工具。它最大的特点是采用独立备份服务器的架构。
PostgreSQL 主库通过 Barman 集中归档 WAL 与备份数据
Barman 支持两种传输模式:
在备份服务器上安装 Barman:
1# Ubuntu / Debian2apt-get install barman34# CentOS / RHEL(需要 PGDG 源)5yum install barman配置文件 /etc/barman.conf(全局配置):
1[barman]2barman_user = barman3configuration_files_directory = /etc/barman.d4barman_home = /var/lib/barman5log_file = /var/log/barman/barman.log6log_level = INFO7compression = gzip8parallel_jobs = 49retention_policy = RECOVERY WINDOW OF 7 DAYS10minimum_redundancy = 1配置 PostgreSQL 服务器 /etc/barman.d/pg-prod.conf:
1[pg-prod]2description = "Production PostgreSQL Server"3ssh_command = ssh postgres@192.168.1.104conninfo = host=192.168.1.10 user=barman dbname=postgres5streaming_conninfo = host=192.168.1.10 user=streaming_barman dbname=postgres6backup_method = postgres7streaming_archiver = on8slot_name = barman9create_slot = auto10retention_policy = RECOVERY WINDOW OF 14 DAYS1112; 并行备份13parallel_jobs = 4在 PostgreSQL 服务器上配置:
1-- 创建 barman 超级用户2CREATE ROLE barman WITH LOGIN SUPERUSER PASSWORD 'barman_password';34-- 创建流复制用户5CREATE ROLE streaming_barman WITH LOGIN REPLICATION PASSWORD 'streaming_password';67-- pg_hba.conf 添加8-- host all barman 192.168.1.20/32 md59-- host replication streaming_barman 192.168.1.20/32 md5PostgreSQL 参数调整(postgresql.conf):
1wal_level = replica2max_wal_senders = 43max_replication_slots = 44archive_mode = on5archive_command = 'barman-wal-archive 192.168.1.20 pg-prod %p'1# 检查配置是否正确2barman check pg-prod34# 查看服务器状态5barman status pg-prod67# 执行全量备份8barman backup pg-prod910# 查看备份列表11barman list-backup pg-prod1213# 查看备份详情14barman show-backup pg-prod latest1516# PITR:恢复到指定时间点17barman recover pg-prod latest /var/lib/pgsql/16/data \18 --target-time "2026-05-06 10:30:00" \19 --remote-ssh-command "ssh postgres@192.168.1.10"2021# 删除过期备份22barman delete pg-prod oldest2324# 手动执行 WAL 切换25barman switch-wal --force --archive pg-prodBarman 从 3.0 版本开始支持块级增量备份(基于 pg_combinebackup,需要 PostgreSQL 17+),对于更早的版本则采用 rsync 模式的文件级增量。
WAL 持续归档是 Barman 的核心能力之一。只要 WAL 文件完整,就可以恢复到备份时间范围内的任意时间点:
1# 恢复到精确时间点2barman recover pg-prod latest /data/pg_restore \3 --target-time "2026-05-06 14:35:22.123456+08"45# 恢复到指定事务 ID6barman recover pg-prod latest /data/pg_restore \7 --target-xid "12345678"89# 恢复到指定 LSN10barman recover pg-prod latest /data/pg_restore \11 --target-lsn "0/1A2B3C4D"Barman 支持将备份存储到云端对象存储:
1# 备份到 S32barman-cloud-backup --cloud-provider aws-s3 \3 -e AES256 \4 --gzip \5 s3://my-pg-backups/ pg-prod67# 从 S3 恢复8barman-cloud-restore --cloud-provider aws-s3 \9 s3://my-pg-backups/ pg-prod latest /data/pg_restore1011# WAL 归档到 S3(替换 archive_command)12# archive_command = 'barman-cloud-wal-archive s3://my-pg-backups/ pg-prod %p'优点:
缺点:
pgBackRest 是由 David Steele 创建的 PostgreSQL 备份工具,用 C 语言编写,以极致性能著称。它不要求独立的备份服务器(虽然也支持),可以在 PG 服务器本地运行。
pgBackRest 将 PostgreSQL 备份写入本地、NFS 或云对象存储
1# Ubuntu / Debian2apt-get install pgbackrest34# CentOS / RHEL(PGDG 源)5yum install pgbackrest67# 从源码编译(获取最新版本)8git clone https://github.com/pgbackrest/pgbackrest.git9cd pgbackrest/src && ./configure && make10cp pgbackrest /usr/bin/pgBackRest 配置文件 /etc/pgbackrest/pgbackrest.conf:
1[global]2# 备份仓库配置 - 本地3repo1-path=/backup/pgbackrest4repo1-retention-full=45repo1-retention-diff=76repo1-cipher-type=aes-256-cbc7repo1-cipher-pass=your-encryption-key89# 备份仓库配置 - S3(可同时配多个仓库)10repo2-type=s311repo2-s3-bucket=my-pg-backups12repo2-s3-region=us-east-113repo2-s3-endpoint=s3.amazonaws.com14repo2-s3-key=YOUR_S3_ACCESS_KEY15repo2-s3-key-secret=YOUR_S3_SECRET_KEY16repo2-retention-full=217repo2-cipher-type=aes-256-cbc18repo2-cipher-pass=your-encryption-key1920# 性能调优21process-max=422compress-type=zst23compress-level=324delta=y2526# 日志27log-level-console=info28log-level-file=detail2930[pg-prod]31pg1-path=/var/lib/pgsql/16/data32pg1-port=543233pg1-user=postgresPostgreSQL 配置(postgresql.conf):
1archive_mode = on2archive_command = 'pgbackrest --stanza=pg-prod archive-push %p'3wal_level = replica4max_wal_senders = 3初始化 Stanza:
1# 创建 stanza(相当于初始化备份仓库)2pgbackrest --stanza=pg-prod stanza-create34# 检查配置5pgbackrest --stanza=pg-prod checkpgBackRest 支持三种备份类型,这是它的一大优势:
1# 全量备份(Full):备份所有数据2pgbackrest --stanza=pg-prod --type=full backup34# 差异备份(Differential):备份自上次全量以来的变化5pgbackrest --stanza=pg-prod --type=diff backup67# 增量备份(Incremental):备份自上次任意备份以来的变化8pgbackrest --stanza=pg-prod --type=incr backup三者的区别:
推荐的备份策略:
周日 00:00 → 全量备份(Full) 周三 00:00 → 差异备份(Diff) 每天 00:00 → 增量备份(Incr)
1# 恢复到最新状态2pgbackrest --stanza=pg-prod --delta restore34# PITR:恢复到指定时间5pgbackrest --stanza=pg-prod --delta \6 --type=time --target="2026-05-06 10:30:00+08" \7 --target-action=promote \8 restore910# 恢复到指定备份11pgbackrest --stanza=pg-prod --delta \12 --set=20260506-003000F \13 restore1415# 恢复单个数据库(选择性恢复)16pgbackrest --stanza=pg-prod --delta \17 --db-include=mydb \18 restore--delta 参数非常实用:它会比较目标目录中已存在的文件,只恢复有差异的部分,大幅加速恢复过程。
多仓库备份(同时写本地 + S3):
1# 备份会同时写入 repo1(本地)和 repo2(S3)2pgbackrest --stanza=pg-prod --type=full backup备份信息查看:
1# 查看所有备份2pgbackrest --stanza=pg-prod info34# 输出示例5stanza: pg-prod6 status: ok7 cipher: aes-256-cbc89 db (current)10 wal archive min/max (16): 00000001000000000000001A/00000001000000000000005F1112 full backup: 20260503-000000F13 timestamp start/stop: 2026-05-03 00:00:00+08 / 2026-05-03 00:45:22+0814 wal start/stop: 00000001000000000000001A / 00000001000000000000001D15 database size: 150GB, database backup size: 150GB16 repo1: backup set size: 38GB, backup size: 38GB1718 diff backup: 20260506-000000D19 timestamp start/stop: 2026-05-06 00:00:00+08 / 2026-05-06 00:12:15+0820 wal start/stop: 00000001000000000000004B / 00000001000000000000004E21 database size: 152GB, database backup size: 8.5GB22 repo1: backup set size: 40.1GB, backup size: 2.1GB备份验证:
1# 验证备份完整性(不实际恢复,只检查文件)2pgbackrest --stanza=pg-prod --set=20260506-000000D verify优点:
缺点:
一句话选型建议:
不管你用哪个工具,备份策略的金标准是 3-2-1 规则:
结合 RPO(恢复点目标)和 RTO(恢复时间目标),我们可以设计出不同等级的备份方案:
1#!/bin/bash2# mysql_backup.sh - MySQL 自动备份脚本3# 策略:周日全量,周一到周六增量45set -euo pipefail67# ====== 配置区域 ======8BACKUP_BASE="/backup/mysql"9MYSQL_USER="backup_user"10MYSQL_PASS="backup_password"11RETENTION_DAYS=1412FULL_BACKUP_DAY=0 # 0=周日13PARALLEL=414COMPRESS_THREADS=415LOG_FILE="/var/log/mysql_backup.log"1617# ====== 函数定义 ======18log() {19 echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"20}2122get_latest_full() {23 ls -dt "$BACKUP_BASE"/full_* 2>/dev/null | head -124}2526get_latest_backup() {27 local latest_inc=$(ls -dt "$BACKUP_BASE"/inc_* 2>/dev/null | head -1)28 local latest_full=$(get_latest_full)29 if [[ -n "$latest_inc" && "$latest_inc" > "$latest_full" ]]; then30 echo "$latest_inc"31 else32 echo "$latest_full"33 fi34}3536cleanup_old_backups() {37 log "清理 ${RETENTION_DAYS} 天前的备份..."38 find "$BACKUP_BASE" -maxdepth 1 -type d -mtime +${RETENTION_DAYS} -exec rm -rf {} \;39}4041# ====== 主逻辑 ======42mkdir -p "$BACKUP_BASE"4344DAY_OF_WEEK=$(date +%w)45DATE_TAG=$(date +%Y%m%d_%H%M%S)4647if [[ "$DAY_OF_WEEK" -eq "$FULL_BACKUP_DAY" ]] || [[ -z "$(get_latest_full)" ]]; then48 # 全量备份49 TARGET="$BACKUP_BASE/full_${DATE_TAG}"50 log "开始全量备份 → $TARGET"51 xtrabackup --backup \52 --user="$MYSQL_USER" --password="$MYSQL_PASS" \53 --target-dir="$TARGET" \54 --parallel="$PARALLEL" \55 --compress --compress-threads="$COMPRESS_THREADS" \56 2>> "$LOG_FILE"57 log "全量备份完成"58else59 # 增量备份60 BASE_DIR=$(get_latest_backup)61 TARGET="$BACKUP_BASE/inc_${DATE_TAG}"62 log "开始增量备份 → $TARGET (基于 $BASE_DIR)"63 xtrabackup --backup \64 --user="$MYSQL_USER" --password="$MYSQL_PASS" \65 --target-dir="$TARGET" \66 --incremental-basedir="$BASE_DIR" \67 --parallel="$PARALLEL" \68 --compress --compress-threads="$COMPRESS_THREADS" \69 2>> "$LOG_FILE"70 log "增量备份完成"71fi7273cleanup_old_backups7475# 验证备份76BACKUP_SIZE=$(du -sh "$TARGET" | cut -f1)77log "备份大小: $BACKUP_SIZE"7879# 上传到 S3(可选)80# aws s3 sync "$TARGET" "s3://my-backups/mysql/${DATE_TAG}/" --storage-class STANDARD_IA8182log "备份流程结束"1#!/bin/bash2# pg_backup.sh - PostgreSQL 自动备份脚本3# 策略:周日全量,周三差异,其他天增量45set -euo pipefail67STANZA="pg-prod"8LOG_FILE="/var/log/pg_backup.log"910log() {11 echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"12}1314DAY_OF_WEEK=$(date +%w)1516case $DAY_OF_WEEK in17 0)18 BACKUP_TYPE="full"19 ;;20 3)21 BACKUP_TYPE="diff"22 ;;23 *)24 BACKUP_TYPE="incr"25 ;;26esac2728log "开始 ${BACKUP_TYPE} 备份 (stanza: ${STANZA})"2930pgbackrest --stanza="$STANZA" --type="$BACKUP_TYPE" backup 2>> "$LOG_FILE"3132if [[ $? -eq 0 ]]; then33 log "${BACKUP_TYPE} 备份成功"34else35 log "ERROR: ${BACKUP_TYPE} 备份失败!"36 # 发送告警(邮件/钉钉/企业微信)37 # curl -s -X POST "https://webhook.example.com" -d "{\"msg\": \"PG backup failed!\"}"38 exit 139fi4041# 输出备份信息42pgbackrest --stanza="$STANZA" info 2>> "$LOG_FILE" | tee -a "$LOG_FILE"4344log "备份流程结束"1# MySQL 备份 - 每天凌晨 2 点20 2 * * * /opt/scripts/mysql_backup.sh >> /var/log/mysql_backup_cron.log 2>&134# PostgreSQL 备份 - 每天凌晨 3 点50 3 * * * /opt/scripts/pg_backup.sh >> /var/log/pg_backup_cron.log 2>&167# 备份验证 - 每周一早上 6 点(仅 pgBackRest)80 6 * * 1 pgbackrest --stanza=pg-prod verify >> /var/log/pg_verify.log 2>&1910# WAL 清理检查 - 每天中午110 12 * * * barman cron >> /var/log/barman_cron.log 2>&1
按数据库类型、数据规模与管理方式选择备份工具
备份这个事情,技术上并不难,难的是坚持做、定期验证。我见过太多人备份做得挺勤,但从来没恢复演练过,等到真需要恢复的时候才发现备份文件是坏的。
我的建议是:
verify 命令就是干这个的记住那句老话:没有经过恢复验证的备份,等于没有备份。
希望这篇对比文章能帮你选对工具,守护好你的数据。有问题欢迎留言讨论。
本章介绍了以下核心内容: