PostgreSQL 备份与恢复指南:3种方法让数据滴水不漏

概述

数据丢了,再好的代码也救不回来。

很多开发者觉得备份是运维的事,自己搭个环境跑通就完事了。等到删库跑路的那一刻,才追悔莫及。PostgreSQL 内置了成熟的备份方案,不需要额外买工具,今天就把这3种最常用的备份方式讲清楚。

准备工作

需要满足以下条件:

  1. 一台已安装 PostgreSQL 的服务器。可以用 apt install postgresql(Ubuntu)或 yum install postgresql-server(CentOS)搞定。
  2. 足够的磁盘空间。备份文件至少预留原始数据 1.5 倍的空间。
  3. 基本的命令行操作能力。所有操作都在终端完成。

搭建步骤

方法一:pg_dump 逻辑备份(最常用)

pg_dump 是 PostgreSQL 自带的逻辑备份工具。它会导出 SQL 语句,兼容性最好,跨版本也没问题。

备份单个数据库

sudo -u postgres pg_dump mydb > mydb_backup.sql

这条命令会把 mydb 数据库的全部数据导出成 SQL 文件。

备份所有数据库

sudo -u postgres pg_dumpall > all_databases_backup.sql

压缩备份,节省空间

sudo -u postgres pg_dump -Fc mydb > mydb_backup.dump

-Fc 是自定义压缩格式。比 SQL 文本小很多,而且支持并行恢复。

指定备份时间点(PITR 前置)

sudo -u postgres pg_dump -F c -b -v -f full_backup.dump --blobs mydb

-b 表示同时备份大对象(如图片附件),-v 显示详细进度。

恢复备份

# 创建目标数据库
sudo -u postgres createdb mydb_restored

# 从 SQL 文件恢复
psql -U postgres -d mydb_restored -f mydb_backup.sql

# 从自定义格式恢复
pg_restore -U postgres -d mydb_restored mydb_backup.dump

方法二:pg_basebackup 物理备份(全库热备)

pg_basebackup 是直接复制数据文件的物理备份。适合大规模数据库,备份速度快,恢复也更快。

执行全量备份

sudo -u postgres pg_basebackup -D /backup/postgresql/full -Fp -Xs -P -h 127.0.0.1 -p 5432

参数说明:

  • -D 指定备份目录
  • -Fp 使用平面文件(不是 tar 包)
  • -Xs 同时复制 WAL 日志
  • -P 显示进度

配置流复制(持续备份基础)

# 编辑 postgresql.conf
sudo vim /etc/postgresql/16/main/postgresql.conf

找到并修改以下配置:

wal_level = replica
max_wal_senders = 5
wal_keep_size = 1GB
# 编辑 pg_hba.conf 允许流复制
sudo vim /etc/postgresql/16/main/pg_hba.conf

添加一行:

host    replication     all             0.0.0.0/0               md5
# 重启生效
sudo systemctl restart postgresql

方法三:crontab 自动化备份(推荐配置)

手工备份容易忘。用 crontab 自动跑,省心。

编写备份脚本

sudo vim /opt/scripts/pg_backup.sh

写入以下内容:

#!/bin/bash
BACKUP_DIR="/backup/postgresql/cron"
DATE=$(date +%Y%m%d_%H%M%S)
DB_NAME="mydb"
KEEP_DAYS=7

mkdir -p $BACKUP_DIR

# 使用自定义格式压缩备份
sudo -u postgres pg_dump -Fc $DB_NAME > $BACKUP_DIR/${DB_NAME}_${DATE}.dump

# 删除7天前的旧备份
find $BACKUP_DIR -name "*.dump" -mtime +${KEEP_DAYS} -delete

echo "$(date): $DB_NAME backup completed" >> $BACKUP_DIR/backup.log
# 添加执行权限
sudo chmod +x /opt/scripts/pg_backup.sh

配置定时任务

crontab -e

添加这一行,每天凌晨3点备份:

0 3 * * * /opt/scripts/pg_backup.sh

验证自动备份

# 查看备份文件
ls -lh /backup/postgresql/cron/

# 查看备份日志
tail -f /backup/postgresql/cron/backup.log

验证部署

按以下方式确认备份有效:

  1. 检查备份文件大小ls -lh /backup/postgresql/cron/,文件不能是0字节。
  2. 恢复测试:在测试环境创建新库,导入备份,确认数据完整。
  3. 检查 crontab 状态crontab -l,确认定时任务已保存。
# 快速验证:导入备份到一个测试库
sudo -u postgres createdb test_restore
pg_restore -U postgres -d test_restore /backup/postgresql/cron/$(ls /backup/postgresql/cron/ | tail -1)
sudo -u postgres psql -d test_restore -c "SELECT count(*) FROM your_table;"

常见问题

Q1:备份时数据库正在写入数据,会不会出错?

不会。pg_dump 在备份开始时获取一个快照,后续写入不会影响备份一致性。如果数据量特别大,可以考虑用 -j 参数并行备份:pg_dump -j 4 -Fc mydb > backup.dump

Q2:备份文件太大了怎么办?

-Fc 压缩格式,通常能缩小到原始大小的 30%-50%。如果还不够,可以加 -Z 9 开到最大压缩:pg_dump -Fc -Z 9 mydb > backup.dump

Q3:如何备份到远程服务器?

最简单的方式是用 rsync

rsync -avz /backup/postgresql/cron/ user@remote-server:/backup/postgresql/

如果想一步到位,pg_dump 直接输出到远程:

sudo -u postgres pg_dump -Fc mydb | ssh user@remote-server "cat > /backup/mydb.dump"

Q4:PostgreSQL 版本升级时备份还可用吗?

pg_dump 导出的 SQL 文件跨版本兼容性好。从 PG 14 导出,导入到 PG 16 完全没问题。但 pg_basebackup 不行,升级前一定要用 pg_dump 做一次逻辑备份,以防万一。


数据这东西,用的时候没感觉,丢了才知道多要命。花10分钟配好自动备份,能省去后面10小时的补救。

选一种方式先跑起来,明天再来后悔也来得及。

这篇文章对你有帮助吗?