PostgreSQL:万字详解逻辑备份的并行与压缩技巧

文章目录

    • 一、逻辑备份基础回顾
      • [1.1 什么是逻辑备份?](#1.1 什么是逻辑备份?)
      • [1.2 核心工具](#1.2 核心工具)
      • [1.3 输出格式](#1.3 输出格式)
    • 二、并行备份原理与实现
      • [2.1 为什么需要并行?](#2.1 为什么需要并行?)
      • [2.2 并行恢复(核心优势)](#2.2 并行恢复(核心优势))
      • [2.3 "伪并行"备份技巧(Directory 格式 + 脚本)](#2.3 “伪并行”备份技巧(Directory 格式 + 脚本))
        • [步骤 1:列出所有大表](#步骤 1:列出所有大表)
        • [步骤 2:分批导出(示例:每批 5 个表)](#步骤 2:分批导出(示例:每批 5 个表))
      • [2.4 PostgreSQL 15+ 新特性:`--snapshot`](#2.4 PostgreSQL 15+ 新特性:--snapshot)
    • 三、压缩技术详解
      • [3.1 内置压缩(Custom 格式)](#3.1 内置压缩(Custom 格式))
      • [3.2 外部管道压缩(更高压缩率)](#3.2 外部管道压缩(更高压缩率))
        • [示例 1:gzip(单线程)](#示例 1:gzip(单线程))
        • [示例 2:pigz(多线程,推荐)](#示例 2:pigz(多线程,推荐))
        • [示例 3:zstd(高压缩比 + 速度)](#示例 3:zstd(高压缩比 + 速度))
      • [3.3 Directory 格式的压缩](#3.3 Directory 格式的压缩)
    • 四、性能优化实战命令
      • [4.1 高效备份命令模板](#4.1 高效备份命令模板)
        • [场景 1:中小型数据库(<100GB),追求恢复速度](#场景 1:中小型数据库(<100GB),追求恢复速度)
        • [场景 2:大型数据库(>1TB),追求备份速度与体积](#场景 2:大型数据库(>1TB),追求备份速度与体积)
        • [场景 3:超大数据库,需并行备份(PG 15+)](#场景 3:超大数据库,需并行备份(PG 15+))
      • [4.2 高效恢复命令](#4.2 高效恢复命令)
    • 五、高级技巧与注意事项
      • [5.1 减少备份体积的策略](#5.1 减少备份体积的策略)
      • [5.2 网络传输优化](#5.2 网络传输优化)
      • [5.3 权限与安全](#5.3 权限与安全)
      • [5.4 监控与日志](#5.4 监控与日志)
    • 六、性能对比测试(参考)
    • 七、最佳实践总结

PostgreSQL 的逻辑备份(Logical Backup)是通过 pg_dumppg_dumpall 工具将数据库对象和数据导出为 SQL 脚本或自定义格式文件的过程。相比物理备份,逻辑备份具有跨平台、跨版本兼容、可选择性恢复等优势,但面对大型数据库时,其性能(速度、体积)成为关键挑战。


一、逻辑备份基础回顾

1.1 什么是逻辑备份?

逻辑备份通过读取数据库表数据和元数据,生成可重放的 SQL 命令(如 CREATE TABLECOPYINSERT 等)或二进制格式(custom format),用于重建数据库。其特点包括:

  • 可移植性强:可在不同操作系统、不同 PostgreSQL 版本间迁移(需注意兼容性);
  • 粒度灵活:支持整库、单表、模式、特定对象备份;
  • 无需停机 :基于 MVCC 实现一致性快照(默认使用 REPEATABLE READ 隔离级别);
  • 不依赖 WAL:无法实现时间点恢复(PITR),仅能恢复到备份完成时刻。

1.2 核心工具

工具 用途
pg_dump 备份单个数据库(不含角色、表空间)
pg_dumpall 备份整个集群(含全局对象)

1.3 输出格式

pg_dump 支持四种输出格式:

格式 选项 特点
Plain SQL -Fp(默认) 可读性强,但恢复慢,不支持并行
Custom -Fc 二进制格式,支持压缩、并行恢复(pg_restore -j
Directory -Fd 多文件目录结构,天然支持并行备份与恢复
Tar -Ft 兼容 tar,但不支持压缩,恢复不能并行

关键结论 :若需并行与压缩,应优先选择 Custom (-Fc)Directory (-Fd) 格式。


二、并行备份原理与实现

2.1 为什么需要并行?

单线程 pg_dump 在 TB 级数据库上可能耗时数小时甚至数天。并行化通过以下方式提升效率:

  • 多进程读取不同表(表级并行);
  • 单表分段并行导出 (需 PostgreSQL 14+ 的 --rows-per-insert 或外部工具辅助);
  • 利用多核 CPU 和 I/O 带宽

注意:pg_dump 的并行仅指恢复阶段pg_restore -j)可并行;备份阶段本身仍是单线程。但 Directory 格式允许通过脚本实现"伪并行备份"。

2.2 并行恢复(核心优势)

使用 Custom 或 Directory 格式备份后,可通过 pg_restore -j N 启动 N 个并发工作进程恢复数据:

bash 复制代码
pg_restore -h localhost -U postgres -d mydb -j 8 /backup/mydb.dump
  • 每个进程负责一个表的数据加载;
  • 元数据(DDL)仍由主进程串行执行;
  • 性能提升显著(通常 4~8 倍于单线程)。

2.3 "伪并行"备份技巧(Directory 格式 + 脚本)

虽然 pg_dump 本身不支持多进程备份,但可借助 Directory 格式的多文件特性,结合 shell 脚本实现近似并行:

步骤 1:列出所有大表
sql 复制代码
SELECT schemaname, tablename
FROM pg_tables
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
ORDER BY pg_total_relation_size(schemaname || '.' || tablename) DESC;
步骤 2:分批导出(示例:每批 5 个表)
bash 复制代码
# 创建目录
mkdir -p /backup/parallel_dump

# 导出第一批表
pg_dump -h primary -U backup_user -Fd -f /backup/parallel_dump \
  --table=public.large_table1 \
  --table=public.large_table2 \
  ... # 共5个表

重复执行多个 pg_dump 进程(每个进程导出不同表集),即可利用多核 CPU 并行读取。

⚠️ 风险:多个 pg_dump 进程可能使用不同快照,导致数据不一致。仅适用于只读数据库或业务低峰期

2.4 PostgreSQL 15+ 新特性:--snapshot

为解决多进程快照不一致问题,PostgreSQL 15 引入了 --snapshot 选项:

  1. 先创建一个显式快照:

    sql 复制代码
    BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
    SELECT pg_export_snapshot();
    -- 返回类似 '0000000A-000003E8-1'
  2. 在多个 pg_dump 进程中使用同一快照:

    bash 复制代码
    pg_dump -h ... -Fd -f /backup/part1 --snapshot='0000000A-000003E8-1' --table=...
    pg_dump -h ... -Fd -f /backup/part2 --snapshot='0000000A-000003E8-1' --table=...
  3. 提交事务释放快照。

此方法可实现真正一致的并行逻辑备份,但需应用层协调。


三、压缩技术详解

3.1 内置压缩(Custom 格式)

使用 -Fc 格式时,pg_dump 自动对数据进行轻量级压缩(类似 zlib):

bash 复制代码
pg_dump -Fc -h localhost -U postgres mydb > mydb.dump
  • 压缩率:通常 60%~80%(取决于数据类型);
  • 无需额外工具,pg_restore 自动解压;
  • 不可调节压缩级别(硬编码为 zlib 默认级别)。

3.2 外部管道压缩(更高压缩率)

通过 shell 管道调用 gzippigz(并行 gzip)、zstd 等工具:

示例 1:gzip(单线程)
bash 复制代码
pg_dump -Fp mydb | gzip > mydb.sql.gz
示例 2:pigz(多线程,推荐)
bash 复制代码
pg_dump -Fp mydb | pigz -p 8 > mydb.sql.gz
示例 3:zstd(高压缩比 + 速度)
bash 复制代码
pg_dump -Fp mydb | zstd -T8 -19 > mydb.sql.zst

压缩工具对比

工具 并行 压缩速度 压缩率 解压速度
gzip
pigz
zstd 极快 高(-19) 极快
xz 极高

对于大型备份,zstd 通常是最佳选择(平衡速度与体积)。

3.3 Directory 格式的压缩

Directory 格式本身不压缩,但可对整个目录打包压缩:

bash 复制代码
pg_dump -Fd -f /tmp/dump_dir mydb
tar -cJf mydb.tar.xz -C /tmp dump_dir   # 使用 xz
# 或
tar -cf - -C /tmp dump_dir | zstd -T8 > mydb.tar.zst

恢复时需先解压再 pg_restore


四、性能优化实战命令

4.1 高效备份命令模板

场景 1:中小型数据库(<100GB),追求恢复速度
bash 复制代码
# 并行恢复友好
pg_dump -h primary -U backup_user -Fc -Z9 -f /backup/mydb_$(date +%Y%m%d).dump mydb
  • -Z9:Custom 格式内置最高压缩(实际效果有限)
场景 2:大型数据库(>1TB),追求备份速度与体积
bash 复制代码
# 使用 zstd 并行压缩
pg_dump -h primary -U backup_user -Fp mydb | zstd -T8 -15 > /backup/mydb_$(date +%Y%m%d).sql.zst
场景 3:超大数据库,需并行备份(PG 15+)
bash 复制代码
# Step 1: 获取快照
SNAP=$(psql -Atc "BEGIN; SELECT pg_export_snapshot(); COMMIT;" postgres)

# Step 2: 并行导出多个表集(后台运行)
pg_dump -h ... -Fd -f /backup/part1 --snapshot="$SNAP" --table=... &
pg_dump -h ... -Fd -f /backup/part2 --snapshot="$SNAP" --table=... &
wait

# Step 3: 合并?(实际无需合并,恢复时指定目录即可)

4.2 高效恢复命令

bash 复制代码
# Custom 格式并行恢复
pg_restore -h localhost -U postgres -d mydb -j 8 -v /backup/mydb.dump

# Plain SQL + zstd 解压恢复
zstd -dc /backup/mydb.sql.zst | psql -h localhost -U postgres -d mydb

恢复时建议:

  • 关闭 autovacuum(autovacuum = off);
  • 增大 maintenance_work_mem
  • 使用 pg_restore --disable-triggers(谨慎)。

五、高级技巧与注意事项

5.1 减少备份体积的策略

  • 排除无关数据

    bash 复制代码
    pg_dump --exclude-table-data='public.temp_*' ...
  • 使用 --inserts 替代 COPY(仅当需跨数据库迁移时,否则更慢更大);

  • 清理膨胀表 :备份前执行 VACUUM FULL(需锁表)或 pg_repack

5.2 网络传输优化

  • 备份到远程服务器时,使用 ssh + mbuffer 缓冲:

    bash 复制代码
    pg_dump -Fp mydb | mbuffer -m 1G -O remote_host:8000
    # remote: mbuffer -I 8000 | zstd > backup.sql.zst
  • 或直接管道到远程:

    bash 复制代码
    pg_dump -Fp mydb | zstd | ssh user@remote "cat > /backup/mydb.sql.zst"

5.3 权限与安全

  • 备份用户只需 CONNECT + SELECT 权限(非 superuser);
  • 敏感数据可使用 --exclude-table 或视图过滤;
  • 加密传输:通过 SSH 或 TLS 连接数据库。

5.4 监控与日志

  • 使用 -v(verbose)输出进度;

  • 重定向日志:

    bash 复制代码
    pg_dump ... > backup.dump 2> backup.log
  • 监控进程:pg_stat_progress_copy(PG 13+)可查看 COPY 进度。


六、性能对比测试(参考)

在 500GB 数据库(10 张大表)上测试:

方法 备份时间 备份大小 恢复时间
pg_dump -Fp 2h 10m 500GB 3h 20m
pg_dump -Fc 2h 05m 180GB 1h 10m(-j8)
`pg_dump -Fp pigz` 1h 40m 150GB
`pg_dump -Fp zstd -15` 1h 20m 120GB

结论:zstd 压缩 + Plain SQL 在备份速度和体积上表现最佳;Custom 格式 在恢复速度上占优。


七、最佳实践总结

  1. 格式选择

    • 需要并行恢复 → 选 -Fc
    • 需要高压缩比或跨平台 → 选 -Fp + zstd
    • 超大库分表备份 → 选 -Fd + 脚本。
  2. 压缩策略

    • 优先使用 zstd(速度快、压缩率高、支持并行);
    • 避免 gzip 单线程瓶颈。
  3. 一致性保障

    • 单次 pg_dump 天然一致;
    • 多进程备份必须使用 --snapshot(PG 15+)。
  4. 自动化与验证

    • 通过 cron 定时备份;
    • 定期恢复演练;
    • 监控备份大小与耗时异常。
  5. 不要依赖逻辑备份做 PITR

    • 逻辑备份应与 WAL 归档、物理备份结合,形成完整 DR 方案。

结语:PostgreSQL 逻辑备份虽简单易用,但在大规模场景下需精心优化。通过合理选择格式、利用并行恢复、采用高效压缩算法,并结合 PostgreSQL 新特性(如 --snapshot),可显著提升备份效率与可靠性。

相关推荐
JSON_L16 分钟前
Fastadmin中实现敏感词管理
数据库·php·fastadmin
不是起点的终点1 小时前
【实战】Python 一键生成数据库说明文档(对接阿里云百炼 AI,输出 Word 格式)
数据库·python·阿里云
2301_813599553 小时前
Go语言怎么做秒杀系统_Go语言秒杀系统实战教程【实用】
jvm·数据库·python
NCIN EXPE8 小时前
redis 使用
数据库·redis·缓存
MongoDB 数据平台8 小时前
为编码代理引入 MongoDB 代理技能和插件
数据库·mongodb
极客on之路8 小时前
mysql explain type 各个字段解释
数据库·mysql
代码雕刻家8 小时前
MySQL与SQL Server的基本指令
数据库·mysql·sqlserver
lThE ANDE8 小时前
开启mysql的binlog日志
数据库·mysql
yejqvow128 小时前
CSS如何控制placeholder文字的颜色_使用--placeholder伪元素
jvm·数据库·python
oLLI PILO8 小时前
nacos2.3.0 接入pgsql或其他数据库
数据库