PostgreSQL 16 数据备份与还原详解 ---语法、案例与实战
✅ 一、数据备份(Backup)
PostgreSQL 提供逻辑备份 (SQL/自定义格式)和物理备份 (文件系统级),本章聚焦逻辑备份工具:
pg_dump,pg_dumpall,pgAdmin 4。
1.1 使用 pgAdmin 4 备份数据库(图形化操作)
适用场景:开发、测试环境,不熟悉命令行的用户
📌 操作步骤:
- 打开 pgAdmin 4 → 连接服务器 → 展开数据库
- 右键目标数据库 →
Backup... - 设置参数:
- Filename :备份文件路径(如
C:\backup\mydb_backup.sql) - Format :
Plain→ SQL 脚本(可读,兼容性好)Custom→ 二进制格式(支持选择性还原,压缩率高)Directory→ 目录格式(大库推荐)Tar→ tar 归档格式
- Encoding:UTF8(推荐)
- Dump Options :
Only data→ 仅数据Only schema→ 仅结构Only schema + data→ 默认(全量)
- Filename :备份文件路径(如
- 点击
Backup→ 等待完成
✅ 优点 :图形化、易用
❌ 缺点:不适合自动化、大库效率低
1.2 使用 pg_dump 工具备份数据库(命令行)
核心工具 :备份单个数据库
📌 基本语法:
bash
pg_dump [选项] 数据库名 > 备份文件
📌 常用选项:
| 选项 | 说明 |
|---|---|
-h host |
主机地址(默认 localhost) |
-p port |
端口(默认 5432) |
-U user |
用户名 |
-F format |
格式:p(plain), c(custom), d(directory), t(tar) |
-f file |
输出文件(替代 > 重定向) |
-v |
详细模式 |
-j jobs |
并行备份(仅 directory 格式) |
--schema-only |
仅备份结构 |
--data-only |
仅备份数据 |
--table=table_name |
备份指定表 |
--exclude-table=table_name |
排除表 |
✅ 案例1:备份为 SQL 脚本(Plain 格式)
bash
# 备份整个数据库为 SQL 文件(默认格式)
pg_dump -h localhost -p 5432 -U postgres mydb > mydb_full_backup.sql
# 仅备份结构(无数据)
pg_dump -U postgres --schema-only mydb > mydb_schema.sql
# 仅备份数据(无结构)
pg_dump -U postgres --data-only mydb > mydb_data.sql
# 备份指定表
pg_dump -U postgres -t employees -t departments mydb > mydb_selected_tables.sql
# 排除日志表
pg_dump -U postgres --exclude-table=logs mydb > mydb_no_logs.sql
✅ 适用场景:
- 小型数据库
- 需要人工编辑备份文件
- 跨版本迁移(SQL 格式兼容性最好)
✅ 案例2:备份为自定义格式(Custom Format - 推荐)
bash
# 备份为自定义二进制格式(压缩、支持选择性恢复)
pg_dump -U postgres -F c -f mydb_backup.custom mydb
# 并行备份(PostgreSQL 9.3+,仅 directory 格式)
pg_dump -U postgres -F d -j 4 -f mydb_backup_dir mydb
# 带压缩的自定义格式(-Z 0~9,9为最高压缩)
pg_dump -U postgres -F c -Z 6 -f mydb_compressed.backup mydb
✅ 优势:
- 压缩率高(节省空间)
- 支持
pg_restore选择性还原- 支持并行备份/恢复(加速大库操作)
1.3 使用 pg_dumpall 备份整个服务器
备份所有数据库 + 全局对象(角色、表空间、配置等)
📌 基本语法:
bash
pg_dumpall [选项] > 备份文件
✅ 案例3:备份整个 PostgreSQL 实例
bash
# 备份所有数据库 + 全局对象(角色、表空间等)
pg_dumpall -U postgres -h localhost > full_server_backup.sql
# 仅备份全局对象(角色、表空间)
pg_dumpall -U postgres --globals-only > globals_backup.sql
# 仅备份某个数据库(等同 pg_dump)
pg_dumpall -U postgres -l mydb > mydb_via_dumpall.sql
# 带清理命令(恢复时先 DROP 再 CREATE)
pg_dumpall -U postgres -c > full_server_with_clean.sql
⚠️ 注意:
pg_dumpall只支持 Plain 格式(SQL 脚本)- 不能并行备份
- 恢复时需超级用户权限
✅ 二、数据还原(Restore)
2.1 使用 pgAdmin 4 还原数据库
适用场景:开发、测试环境
📌 操作步骤:
- 右键目标数据库 →
Restore... - 选择备份文件(必须与备份格式匹配)
- 设置参数:
- Format:自动识别或手动选择
- Restore options :
Clean before restore→ 先删除现有对象(危险!)Single transaction→ 失败则全回滚Include CREATE DATABASE→ 从备份创建新库
- 点击
Restore
✅ 注意事项:
- 还原前确保目标数据库存在(除非勾选 CREATE DATABASE)
- 还原用户需有目标库的 CREATE 权限
- 大文件还原可能超时 → 调整
Preferences > Miscellaneous > Process timeout
2.2 使用 psql 还原数据库(SQL 格式)
适用 :
pg_dump或pg_dumpall生成的.sql文件
📌 基本语法:
bash
psql [选项] 数据库名 < 备份文件
✅ 案例4:还原 SQL 备份
bash
# 还原到现有数据库(需先创建空库)
createdb -U postgres mydb_restored
psql -U postgres -d mydb_restored < mydb_full_backup.sql
# 还原 pg_dumpall 备份(需超级用户)
psql -U postgres -f full_server_backup.sql postgres
# 注意:pg_dumpall 备份包含 CREATE DATABASE,会自动创建库
# 带事务还原(失败则回滚)
psql -U postgres -d mydb_restored -v ON_ERROR_STOP=1 < mydb_full_backup.sql
# 详细模式 + 错误停止
psql -U postgres -d mydb_restored -v ON_ERROR_STOP=1 -q -f mydb_full_backup.sql
✅ 常用 psql 选项:
-v ON_ERROR_STOP=1→ 遇错停止(推荐)-q→ 静默模式(不显示 SQL)-1→ 单事务模式(等同--single-transaction)
2.3 使用 pg_restore 快速还原数据库(自定义/目录格式)
核心优势 :支持选择性还原 、并行还原 、灵活控制
📌 基本语法:
bash
pg_restore [选项] -d 数据库名 备份文件
📌 常用选项:
| 选项 | 说明 |
|---|---|
-d dbname |
目标数据库 |
-F format |
格式(通常自动识别) |
-c |
还原前清理(DROP 对象) |
-C |
创建数据库(备份中需包含 CREATE DATABASE) |
-j jobs |
并行还原(加速) |
-t table |
仅还原指定表 |
-T table |
排除表 |
-s |
仅还原结构 |
-a |
仅还原数据 |
--single-transaction |
单事务模式 |
✅ 案例5:还原自定义格式备份
bash
# 创建目标数据库
createdb -U postgres mydb_restored
# 完整还原自定义格式备份
pg_restore -U postgres -d mydb_restored mydb_backup.custom
# 并行还原(4个进程)
pg_restore -U postgres -d mydb_restored -j 4 mydb_backup.custom
# 仅还原结构
pg_restore -U postgres -d mydb_restored -s mydb_backup.custom
# 仅还原数据(需结构已存在)
pg_restore -U postgres -d mydb_restored -a mydb_backup.custom
# 还原指定表
pg_restore -U postgres -d mydb_restored -t employees mydb_backup.custom
# 清理后还原(危险!先 DROP 所有对象)
pg_restore -U postgres -d mydb_restored -c mydb_backup.custom
# 单事务模式(失败全回滚)
pg_restore -U postgres -d mydb_restored --single-transaction mydb_backup.custom
✅ 最佳实践:
- 生产环境优先使用
pg_restore(性能好、控制灵活)- 大库还原使用
-j并行加速- 重要操作前先
-s仅还原结构测试
✅ 三、数据库迁移(Migration)
3.1 相同版本 PostgreSQL 之间迁移
最简单场景:直接备份还原
✅ 案例6:同版本迁移(源 → 目标)
bash
# 在源服务器备份
pg_dump -U postgres -F c -f mydb_migration.backup mydb
# 拷贝备份文件到目标服务器
scp mydb_migration.backup user@target-server:/tmp/
# 在目标服务器还原
createdb -U postgres mydb
pg_restore -U postgres -d mydb /tmp/mydb_migration.backup
✅ 推荐 :使用自定义格式 +
pg_restore,支持并行
3.2 不同版本 PostgreSQL 之间迁移
原则 :从低版本 → 高版本(兼容),高→低需特殊处理
✅ 案例7:从 PostgreSQL 14 → 16 迁移
bash
# 在旧版本(14)服务器备份为 SQL 格式(兼容性最好)
pg_dump -U postgres --no-sync -f mydb_v14.sql mydb
# 拷贝到新服务器(16)
scp mydb_v14.sql user@pg16-server:/tmp/
# 在新版本(16)创建数据库并还原
createdb -U postgres mydb
psql -U postgres -d mydb -v ON_ERROR_STOP=1 -f /tmp/mydb_v14.sql
# ✅ 验证数据
psql -U postgres -d mydb -c "SELECT COUNT(*) FROM employees;"
⚠️ 注意:
- 使用
--no-sync避免旧版本不支持的选项- 还原后运行
ANALYZE更新统计信息- 检查扩展是否兼容(如 postgis)
❌ 从高版本 → 低版本?
不推荐 !可能因语法/功能不兼容失败。
替代方案:
- 导出为 CSV + 手动建表
- 使用中间工具(如 pgloader)
- 升级目标服务器版本
3.3 不同数据库之间迁移(如 MySQL → PostgreSQL)
常用工具 :
pgloader,ETL 工具, 手动导出导入
✅ 案例8:使用 pgloader 迁移 MySQL → PostgreSQL
bash
# 安装 pgloader(Linux)
sudo apt-get install pgloader
# 创建迁移配置文件 migrate.load
/*
load database
from mysql://user:pass@localhost/mydb
into postgresql://postgres:pass@localhost/mydb_pg
with include drop, create tables, create indexes, reset sequences
set MySQL PARAMETERS net_read_timeout = '600';
;*/
# 执行迁移
pgloader migrate.load
# ✅ 验证
psql -U postgres -d mydb_pg -c "\dt"
psql -U postgres -d mydb_pg -c "SELECT COUNT(*) FROM users;"
✅ 案例9:手动 CSV 迁移
sql
-- 在源数据库(MySQL)导出 CSV
SELECT * FROM employees INTO OUTFILE '/tmp/employees.csv'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n';
-- 在 PostgreSQL 创建表(需手动匹配结构)
CREATE TABLE employees (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
email VARCHAR(100),
salary NUMERIC(10,2)
);
-- 导入 CSV
COPY employees (id, name, email, salary)
FROM '/tmp/employees.csv'
WITH (FORMAT csv, HEADER true, DELIMITER ',', QUOTE '"');
-- ✅ 验证
SELECT COUNT(*) FROM employees;
✅ 推荐工具:
pgloader:自动化迁移,支持多种源AWS DMS/Azure Data Factory:云环境Python pandas + SQLAlchemy:定制化迁移
✅ 四、综合实战案例
🎯 案例1:生产环境每日自动备份脚本
bash
#!/bin/bash
# 文件名:daily_backup.sh
# 功能:每日自动备份数据库,保留7天
# 配置
DB_NAME="production_db"
BACKUP_DIR="/backup/postgresql"
DATE=$(date +%Y%m%d_%H%M%S)
USER="backup_user" # 需有数据库连接权限
# 创建备份目录
mkdir -p $BACKUP_DIR
# 执行备份(自定义格式 + 压缩)
pg_dump -U $USER -F c -Z 6 -f "$BACKUP_DIR/${DB_NAME}_${DATE}.backup" $DB_NAME
# 记录日志
echo "[$(date)] 备份完成: ${DB_NAME}_${DATE}.backup" >> /var/log/pg_backup.log
# 删除7天前的备份
find $BACKUP_DIR -name "*.backup" -mtime +7 -delete
# 发送通知(可选)
# echo "备份完成" | mail -s "PostgreSQL Backup" admin@company.com
✅ 设置定时任务(crontab):
bash# 每天凌晨2点执行 0 2 * * * /path/to/daily_backup.sh
🎯 案例2:灾难恢复演练(完整流程)
bash
# 1. 模拟灾难:删除数据库
dropdb -U postgres production_db
# 2. 从最近备份恢复
# 假设最新备份:production_db_20250912_020000.backup
# 3. 创建新数据库
createdb -U postgres production_db
# 4. 并行还原(4进程)
pg_restore -U postgres -d production_db -j 4 \
/backup/postgresql/production_db_20250912_020000.backup
# 5. 验证关键表
psql -U postgres -d production_db -c "SELECT COUNT(*) FROM orders;"
psql -U postgres -d production_db -c "SELECT COUNT(*) FROM users;"
# 6. 更新统计信息(优化查询计划)
psql -U postgres -d production_db -c "ANALYZE;"
# 7. 通知团队恢复完成
echo "灾难恢复完成!数据已还原至 2025-09-12 02:00" | mail -s "RECOVERY COMPLETE" team@company.com
🎯 案例3:跨云迁移(AWS RDS PostgreSQL → Azure PostgreSQL)
bash
# 步骤1:从 AWS RDS 备份
pg_dump -h my-rds-instance.xxxxxx.us-east-1.rds.amazonaws.com \
-p 5432 -U master_user \
-F c -Z 6 -f aws_db.backup mydb
# 步骤2:上传到 Azure Blob(或直接下载到本地)
az storage blob upload \
--account-name mystorage \
--container-name backups \
--file aws_db.backup \
--name aws_db.backup
# 步骤3:从 Azure VM 下载并还原到 Azure PostgreSQL
wget https://mystorage.blob.core.windows.net/backups/aws_db.backup
# 创建数据库
createdb -h my-azure-pg.postgres.database.azure.com \
-p 5432 -U admin_user@my-azure-pg mydb_restored
# 还原(Azure 需 SSL)
pg_restore -h my-azure-pg.postgres.database.azure.com \
-p 5432 -U admin_user@my-azure-pg \
-d mydb_restored \
--sslmode=require \
-j 4 \
aws_db.backup
# ✅ 验证连接
psql "host=my-azure-pg.postgres.database.azure.com port=5432 dbname=mydb_restored user=admin_user@my-azure-pg sslmode=require"
✅ 五、常见问题及解答(FAQ)
❓ 疑问1:pg_dump 备份的文件只能在 PostgreSQL 中使用吗?
答案 :基本是的,但有例外:
- Plain 格式(.sql) :
- 可在其他数据库尝试执行(如 MySQL、SQL Server)
- 但大概率失败 !因为:
- PostgreSQL 特有语法(如
SERIAL,JSONB,ILIKE)- 函数不同(
NOW()vsCURRENT_TIMESTAMP)- 数据类型不兼容
- Custom/Directory/Tar 格式 :
- 只能用
pg_restore还原到 PostgreSQL- 是 PostgreSQL 专有二进制格式
✅ 跨数据库迁移正确姿势:
- 使用
pg_dump --data-only --column-inserts导出 INSERT 语句- 手动修改 SQL 语法适配目标数据库
- 使用 ETL 工具(如 pgloader, Talend, Informatica)
- 导出 CSV + 手动建表
bash
# 导出为兼容性较好的 INSERT 语句
pg_dump -U postgres --data-only --column-inserts mydb > mydb_inserts.sql
❓ 疑问2:使用 pgAdmin 恢复数据库时需要注意什么问题?
关键注意事项:
目标数据库必须存在 (除非勾选 "Create Database")
- 否则报错:
database "xxx" does not exist用户权限不足
- 需对目标库有
CREATE权限- 全局对象(角色、表空间)需超级用户
备份格式不匹配
- Custom 格式备份不能用 "Plain" 格式还原
- pgAdmin 通常能自动识别,但手动选错会失败
大文件超时
- 默认超时 120 秒 → 修改:
File > Preferences > Miscellaneous > Process timeout编码问题
- 备份和目标库编码需一致(推荐 UTF8)
- 否则出现乱码或报错
对象冲突
- 表已存在时,需勾选 "Clean before restore"(危险!)
- 或手动先删除目标表
扩展依赖
- 备份中包含
CREATE EXTENSION,目标库需已安装扩展
✅ 安全还原步骤:创建空数据库:
CREATE DATABASE mydb_restored;在 pgAdmin 中右键该库 → Restore
选择备份文件 → Format 选 "Custom"(如适用)
不勾选 "Clean"(除非确定要删除现有数据)
点击 Restore → 监控日志
✅ 六、备份还原最佳实践总结
-
备份策略:
- 全量备份 + WAL 归档(实现 PITR)
- 每日全备,保留 7-30 天
- 关键库增加备份频率
-
工具选择:
- 日常备份 :
pg_dump自定义格式 +pg_restore - 全实例备份 :
pg_dumpall - 图形化操作:pgAdmin 4(开发环境)
- 跨库迁移:pgloader / CSV
- 日常备份 :
-
还原测试:
- 定期演练灾难恢复(至少每季度一次)
- 验证备份文件完整性(
pg_restore -l file.backup)
-
安全与监控:
- 备份文件加密存储
- 监控备份任务是否成功(日志 + 告警)
- 限制备份用户权限(非超级用户)
-
性能优化:
- 大库使用
-j并行备份/恢复 - 使用
directory格式支持并行 - 避开业务高峰期执行
- 大库使用
🚀 黄金法则 :
没有验证的备份 = 没有备份!定期测试还原流程,确保关键时刻能救命!
📚 建议结合 pg_basebackup(物理备份)和 WAL-G(云存储归档)构建企业级备份体系!