S3协议已经成为对象存储领域的事实标准,无论是AWS S3、阿里云OSS、腾讯云COS,还是自建的MinIO、Ceph RGW,都提供了S3兼容的访问接口。把PostgreSQL的备份文件放进对象存储,可以摆脱本地磁盘容量和单点故障的限制,配合版本控制和异地冗余特性,备份的可靠性会明显提升。本文介绍三种把PostgreSQL备份推送到S3协议对象存储的方法,并分析各自的适用场景。

为什么选择S3协议对象存储存放备份
传统的备份方式通常是把备份文件写到本地磁盘或挂载的NFS卷上,这种做法有几个明显的短板。首先是空间问题,随着数据库增长,备份文件会不断膨胀,本地磁盘迟早会成为瓶颈。其次是可靠性问题,服务器本身发生故障时,存放在同一台机器上的备份很可能跟着一起丢失,达不到容灾的基本要求。
对象存储天生就是为了解决这类问题设计的。它容量几乎无限扩展,按使用量计费,不需要提前规划磁盘空间。多数对象存储服务还提供多副本或者纠删码机制,数据持久性通常承诺十一个九以上。此外,S3协议的开放性意味着你不会被某一家厂商绑定,切换存储后端只需要修改endpoint地址,工具链基本不用变。
对于备份场景,建议为备份文件单独创建一个存储桶,并开启版本控制和生命周期策略。版本控制可以防止误删除操作直接抹掉历史备份,生命周期策略则可以自动把老旧备份转为低频存储类型,降低长期保存的成本。
方案一:pg_dump结合管道与AWS CLI上传
最直接的办法是利用Linux的管道机制,把pg_dump的输出流直接交给AWS CLI上传。这种方式不需要在本地落盘临时文件,即使服务器磁盘紧张也能完成备份。AWS CLI对S3协议的支持最为完整,通过--endpoint-url参数可以轻松对接任何S3兼容的存储服务。
#!/bin/bash
# 备份脚本:将数据库备份直接流式上传到S3
BACKUP_DATE=$(date +%Y%m%d_%H%M%S)
DB_NAME="mydb"
BUCKET="pg-backup-bucket"
# 方式一:自定义格式备份,支持并行恢复和选择性恢复表
pg_dump -Fc -d "$DB_NAME" | aws s3 cp - "s3://$BUCKET/$DB_NAME/$BACKUP_DATE.dump" \
--endpoint-url https://minio.example.internal:9000
# 方式二:先压缩再上传,节省存储空间和传输流量
pg_dump -d "$DB_NAME" | gzip | aws s3 cp - "s3://$BUCKET/$DB_NAME/$BACKUP_DATE.sql.gz" \
--endpoint-url https://minio.example.internal:9000这个脚本依赖环境变量中的访问凭证。推荐的做法是为备份创建一个专用的IAM用户或访问密钥,权限只限制在备份桶内,并在服务器的crontab所属用户主目录下配置~/.aws/credentials文件。不要把访问密钥硬编码在脚本里,一旦脚本进入版本库就会造成凭证泄露。
流式上传的缺点是无法在传输前计算校验和,也不方便使用分段上传来加速大文件。如果备份文件超过几个GB,建议先在本地生成文件、计算md5后再用aws s3 cp 文件名 s3://桶名/路径上传,最后把校验和记录到一个清单文件一并上传,恢复前先核对完整性。
方案二:使用pgBackRest专业备份工具
对于数据量较大、对恢复时间有要求的系统,pgBackRest是更合适的选择。它原生支持把S3兼容存储作为备份仓库,支持全量、差异、增量三种备份类型,内置并行压缩、块级校验和备份加密,恢复速度也远快于pg_dump。很多大型生产环境都在用它。
配置的关键在于仓库段中指定存储类型为S3,并填写对应的endpoint、桶名和区域信息。下面是一个对接自建MinIO的完整配置示例,配置文件路径通常为/etc/pgbackrest/pgbackrest.conf:
[global] # 备份仓库指向S3对象存储 repo1-type=s3 repo1-s3-bucket=pg-backup-bucket repo1-s3-endpoint=minio.example.internal:9000 repo1-s3-region=us-east-1 repo1-s3-verify-tls=n # 并行进程数,加快备份和恢复速度 repo1-s3-key=你的AccessKey repo1-s3-key-secret=你的SecretKey process-max=4 # 日志配置 log-level-console=info log-level-file=detail [mydb] pg1-path=/var/lib/postgresql/16/main pg1-port=5432
配置完成后,先初始化stanza再执行备份。pgBackRest会自动在对象存储中创建目录结构,并把存储桶当作本地仓库一样管理全量链和归档的WAL日志:
# 创建并校验stanza sudo -u postgres pgbackrest --stanza=mydb stanza-create # 执行全量备份,写入S3仓库 sudo -u postgres pgbackrest --stanza=mydb backup --type=full # 查看备份集信息 sudo -u postgres pgbackrest --stanza=mydb info
需要注意WAL归档的配合。在postgresql.conf中设置archive_command = 'pgbackrest --stanza=mydb archive-push %p'后,pgBackRest会把归档的WAL也推送到S3仓库,这样就能实现基于时间点的恢复。S3仓库中的备份数据格式是pgBackRest私有的,恢复时必须通过pgBackRest进行,这一点和pg_dump的纯SQL dump完全不同。
方案对比与注意事项
三种方案各有定位。pg_dump加管道上传适合小型数据库和开发测试环境,实现简单、备份文件是通用的SQL或自定义格式;awscli配合脚本适合中等规模、已经有自己运维体系的团队;pgBackRest则面向生产环境的大库,功能最完整但学习成本也最高。如果数据量超过几十GB且有恢复时间目标要求,直接上pgBackRest是省心的选择。
无论采用哪种方案,安全方面有几件事不能省。第一是传输加密,对象存储endpoint务必走HTTPS,避免备份明文暴露在网络中;第二是静态加密,敏感数据建议在应用层用gpg或pgBackRest内置的repo1-cipher-type=aes-256-cbc加密,即使存储凭证泄露,备份内容也不会直接被读取;第三是恢复演练,备份只有在成功恢复过一次之后才算真正有效,建议每季度至少做一次完整的恢复测试。
最后提醒一点,对象存储的桶权限要设置为私有读写,不要为了方便改成公开可读。历史上多次大规模数据泄露事件都源于配置错误的公开存储桶。配合生命周期规则自动清理过期备份,既控制成本,也减少攻击面。把备份验证、监控告警纳入日常巡检,这套基于S3对象存储的备份体系才算真正闭环。
PostgreSQL备份S3对象存储pgBackRest修改时间:2026-09-08 19:38:59