# 备份仓库

> PostgreSQL 的备份存储仓库
---

您可以通过指定 [`pgbackrest_repo`](/zh/docs/pgsql/param/#pgbackrest_repo) 参数来配置**存储备份的位置**。
您可以在那里定义多个仓库，Pigsty 将根据 [`pgbackrest_method`](/zh/docs/pgsql/param/#pgbackrest_method) 的值选择它。

## 默认仓库 {#default-repo}

默认情况下，Pigsty 有两个默认备份仓库定义：`local` 和 `minio` 备份仓库。

- `local`：**默认**，使用本地 `/pg/backup` 目录（软链接指向 [`pg_fs_backup`](/zh/docs/pgsql/param/#pg_fs_backup)：`/data/backups`）
- `minio`：使用 SNSD 1 节点 MinIO 集群（由 pigsty 支持，但默认未启用）

```yaml
pgbackrest_method: local          # 选择备份仓库方法，`local` 或 `minio` 或任何其他用户定义的仓库
pgbackrest_repo:                  # pgbackrest 仓库：https://pgbackrest.org/configuration.html#section-repository
  local:                          # 使用本地 posix fs 的默认 pgbackrest 仓库
    path: /pg/backup              # 本地备份目录，默认为 `/pg/backup`
    retention_full_type: count    # 按数量保留全量备份
    retention_full: 2             # 使用本地 fs 仓库时保留 2 个，最多 3 个全量备份
  minio:                          # pgbackrest 的可选 minio 仓库
    type: s3                      # minio 兼容 s3，所以使用 s3
    s3_endpoint: sss.pigsty       # minio 端点域名，默认为 `sss.pigsty`
    s3_region: us-east-1          # minio 区域，默认 us-east-1，对 minio 无用
    s3_bucket: pgsql              # minio 存储桶名称，默认为 `pgsql`
    s3_key: pgbackrest            # pgbackrest 的 minio 用户访问密钥
    s3_key_secret: S3User.Backup  # pgbackrest 的 minio 用户密钥
    s3_uri_style: path            # 对 minio 使用路径样式 uri 而不是主机样式
    path: /pgbackrest             # minio 备份路径，默认为 `/pgbackrest`
    storage_port: 9000            # minio 端口，默认为 9000
    storage_ca_file: /etc/pki/ca.crt  # minio ca 文件路径，默认为 `/etc/pki/ca.crt`
    block: y                      # 启用块增量备份
    bundle: y                     # 将小文件打包成单个文件
    bundle_limit: 20MiB           # 文件包限制，对象存储为 20MiB
    bundle_size: 128MiB           # 文件包目标大小，对象存储为 128MiB
    cipher_type: aes-256-cbc      # 为远程备份仓库启用 AES 加密
    cipher_pass: pgBackRest       # AES 加密密码，默认为 'pgBackRest'
    retention_full_type: time     # 在 minio 仓库上按时间保留全量备份
    retention_full: 14            # 保留最后 14 天的全量备份
```


--------

## 保留策略 {#repo-retention}

如果您每天备份而不删除它们，备份仓库将越来越大并占满您的磁盘空间。
您需要定义保留策略以仅保留有限数量的备份。

默认备份策略在 [`pgbackrest_repo`](/zh/docs/pgsql/param/#pgbackrest_repo) 参数中定义，根据需要更改它们。

- `local`：保留最后 **2** 个全量备份，备份期间最多 3 个
- `minio`：保留最后 **14** 天内的所有全量备份

--------

## 空间规划 {#space-planning}

对象存储提供几乎无限的存储容量，因此您无需担心磁盘空间。
您可以通过混合全量和差异备份策略优化空间使用。

对于本地磁盘备份仓库，pigsty 建议使用保留最后 **2** 个全量备份的保留策略，
这意味着在磁盘上保留两个最新的全量备份（在运行新备份时可能存在第三个副本）。

这为您提供至少最后 24 小时的保证恢复窗口。详情请查看[备份策略](/zh/docs/pgsql/backup/policy)。

--------

## 仓库替代方案 {#repo-alternative}

您也可以使用其他服务作为备份仓库，详情请查看 [pgbackrest 文档](https://pgbackrest.org/user-guide.html)：

- [S3 兼容对象存储](https://pgbackrest.org/user-guide.html#s3-support)
- [Azure 兼容对象存储](https://pgbackrest.org/user-guide.html#azure-support)
- [GCS 兼容对象存储](https://pgbackrest.org/user-guide.html#gcs-support)
- [SFTP 支持](https://pgbackrest.org/user-guide.html#sftp-support)



--------

## 仓库版本控制 {#repo-versioning}

您甚至可以指定[仓库目标时间](https://pgbackrest.org/user-guide.html#sftp-support#repo-target-time)以获取对象存储的快照。

您可以通过在 [`minio_buckets`](/zh/docs/minio/param#minio_buckets) 中添加 `versioning` 标志来启用 MinIO 版本控制：

```yaml
minio_buckets:
  - { name: pgsql ,versioning: true }
  - { name: meta  ,versioning: true }
  - { name: data }
```


--------

## 仓库锁定 {#repo-locking}

一些对象存储服务（S3、MinIO 等）支持**锁定**，可以防止备份被删除，即使是 DBA 本人。

- [MinIO 对象锁定](https://min.io/docs/minio/linux/administration/object-management/object-retention.html)
- [AWS S3：使用对象锁定锁定对象](https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lock.html)


您可以通过在 [`minio_buckets`](/zh/docs/minio/param#minio_buckets) 中添加 `lock` 标志来启用 MinIO 锁定功能：

```yaml
minio_buckets:
  - { name: pgsql , lock: true }
  - { name: meta ,versioning: true  }
  - { name: data }
```


--------

## 使用对象存储 {#use-object-storage}

对象存储服务提供几乎无限的存储容量，并为您的系统提供远程灾难容错。
如果您没有对象存储，Pigsty 有内置的 [MinIO](/zh/docs/minio) 支持。

### MinIO

您可以通过取消注释以下设置来启用 minio 备份仓库。
请注意，pgbackrest 只接受 HTTPS / 域名，因此您必须使用域名和 HTTPS 端点运行 MinIO。

```yaml
all:
  vars:
    pgbackrest_method: minio      # 使用 minio 作为默认备份仓库
  children:                       # 定义一个单节点 minio SNSD 集群
    minio: { hosts: { 10.10.10.10: { minio_seq: 1 }} ,vars: { minio_cluster: minio }}
```

### S3

如果您只有**一个**节点，有意义的备份策略可能是使用云供应商的对象存储服务，如 AWS S3、阿里云 OSS 或 Google Cloud 等...
要实现这一点，您可以定义一个新的仓库：

```yaml
pgbackrest_method: s3             # 使用 'pgbackrest_repo.s3' 作为备份仓库
pgbackrest_repo:                  # pgbackrest 仓库：https://pgbackrest.org/configuration.html#section-repository

  s3:                             # 阿里云 oss（s3 兼容）对象存储服务
    type: s3                      # oss 兼容 s3
    s3_endpoint: oss-cn-beijing-internal.aliyuncs.com
    s3_region: oss-cn-beijing
    s3_bucket: <your_bucket_name>
    s3_key: <your_access_key>
    s3_key_secret: <your_secret_key>
    s3_uri_style: host
    path: /pgbackrest
    bundle: y                     # 将小文件打包成单个文件
    bundle_limit: 20MiB           # 文件包限制，对象存储为 20MiB
    bundle_size: 128MiB           # 文件包目标大小，对象存储为 128MiB
    cipher_type: aes-256-cbc      # 为远程备份仓库启用 AES 加密
    cipher_pass: pgBackRest       # AES 加密密码，默认为 'pgBackRest'
    retention_full_type: time     # 在 minio 仓库上按时间保留全量备份
    retention_full: 14            # 保留最后 14 天的全量备份

  local:                          # 使用本地 posix fs 的默认 pgbackrest 仓库
    path: /pg/backup              # 本地备份目录，默认为 `/pg/backup`
    retention_full_type: count    # 按数量保留全量备份
    retention_full: 2             # 使用本地 fs 仓库时保留 2 个，最多 3 个全量备份
```




--------

## 管理备份 {#manage-backups}

### 启用备份 {#enable-backup}

如果您的数据库集群是在 [`pgbackrest_enable`](/zh/docs/pgsql/param/#pgbackrest_enable) 设置为 `true` 的情况下创建的，备份将自动启用。

如果是在 `false` 值下创建的，您可以使用以下命令启用 pgbackrest 组件：

```bash
./pgsql.yml -t pg_backup    # 运行 pgbackrest 子任务
```

### 移除备份 {#remove-backup}

Pigsty 在移除主实例（[`pg_role`](/zh/docs/pgsql/param/#pg_role) = `primary`）时会移除 pgbackrest 备份 stanza。

```bash
./pgsql-rm.yml
./pgsql-rm.yml -e pg_rm_backup=false   # 保持备份完整
./pgsql-rm.yml -t pg_backup            # 仅移除备份
```

使用 `pg_backup` 子任务仅移除备份，并使用 [`pg_rm_backup`](/zh/docs/pgsql/param/#pg_rm_backup) 参数保留备份。

如果您的备份仓库被**锁定**（例如，S3 / MinIO 有锁定选项），此操作将失败。

**备份移除**

移除备份可能导致永久数据丢失，这是一个危险操作，请极其谨慎地执行。


### 列出备份 {#list-backup}

此命令将列出 pgbackrest 仓库中的所有备份（由所有集群共享）

```bash
pgbackrest info
````

### 手动备份 {#manual-backup}

Pigsty 有一个内置脚本 `/pg/bin/pg-backup`，它封装了 `pgbackrest` 备份命令。

```bash
pg-backup        # 进行增量备份
pg-backup full   # 进行全量备份
pg-backup incr   # 进行增量备份
pg-backup diff   # 进行差异备份
```

### 基础备份 {#base-backup}

Pigsty 有一个替代备份脚本 `/pg/bin/pg-basebackup`，它不依赖 `pgbackrest`，并为您提供数据库集群的物理副本。
默认备份目录是 `/pg/backup`。

```bash tab="help"
NAME
  pg-basebackup  -- make base backup from PostgreSQL instance

SYNOPSIS
  pg-basebackup -sdfeukr
  pg-basebackup --src postgres:/// --dst . --file backup.tar.lz4

DESCRIPTION
-s, --src, --url     Backup source URL, optional, "postgres:///" by default, if password is required, it should be given in url, ENV or .pgpass
-d, --dst, --dir     Where to put backup files, "/pg/backup" by default
-f, --file           Overwrite default backup filename, "backup_${tag}_${date}.tar.lz4"
-r, --remove         .lz4 Files mtime before n minutes ago will be removed, default is 1200 (20hour)
-t, --tag            Backup file tag, if not set, target cluster_name or local ip address will be used. Also used as part of DEFAULT filename
-k, --key            Encryption key when --encrypt is specified, default key is ${tag}
-u, --upload         Upload backup files to cloud storage, (need your own implementation)
-e, --encryption     Encrypt with RC4 using OpenSSL, if not key is specified, tag is used as key
-h, --help           Print this message
```
```bash tab="backup"
postgres@pg-meta-1:~$ pg-basebackup
[2025-07-13 06:16:05][INFO] ================================================================
[2025-07-13 06:16:05][INFO] [INIT] pg-basebackup begin, checking parameters
[2025-07-13 06:16:05][DEBUG] [INIT] #====== BINARY
[2025-07-13 06:16:05][DEBUG] [INIT] pg_basebackup     :   /usr/pgsql/bin/pg_basebackup
[2025-07-13 06:16:05][DEBUG] [INIT] openssl           :   /usr/bin/openssl
[2025-07-13 06:16:05][DEBUG] [INIT] #====== PARAMETER
[2025-07-13 06:16:05][DEBUG] [INIT] filename  (-f)    :   backup_pg-meta_20250713.tar.lz4
[2025-07-13 06:16:05][DEBUG] [INIT] src       (-s)    :   postgres:///
[2025-07-13 06:16:05][DEBUG] [INIT] dst       (-d)    :   /pg/backup
[2025-07-13 06:16:05][DEBUG] [INIT] tag       (-t)    :   pg-meta
[2025-07-13 06:16:05][DEBUG] [INIT] key       (-k)    :   pg-meta
[2025-07-13 06:16:05][DEBUG] [INIT] encrypt   (-e)    :   false
[2025-07-13 06:16:05][DEBUG] [INIT] upload    (-u)    :   false
[2025-07-13 06:16:05][DEBUG] [INIT] remove    (-r)    :   -mmin +1200
[2025-07-13 06:16:05][INFO] [LOCK] acquire lock @ /tmp/backup.lock
[2025-07-13 06:16:05][INFO] [LOCK] lock acquired success on /tmp/backup.lock, pid=107417
[2025-07-13 06:16:05][INFO] [BKUP] backup begin, from postgres:/// to /pg/backup/backup_pg-meta_20250713.tar.lz4
[2025-07-13 06:16:05][INFO] [BKUP] backup in normal mode
pg_basebackup: initiating base backup, waiting for checkpoint to complete

pg_basebackup: checkpoint completed
pg_basebackup: write-ahead log start point: 0/7000028 on timeline 1
pg_basebackup: write-ahead log end point: 0/7000FD8
pg_basebackup: syncing data to disk ...
pg_basebackup: base backup completed
[2025-07-13 06:16:06][INFO] [BKUP] backup complete!
[2025-07-13 06:16:06][INFO] [RMBK] remove local obsolete backup: 1200
[2025-07-13 06:16:06][INFO] [BKUP] find obsolete backups: find /pg/backup/ -maxdepth 1 -type f -mmin +1200 -name 'backup*.lz4'
[2025-07-13 06:16:06][WARN] [BKUP] remove obsolete backups:
[2025-07-13 06:16:06][INFO] [RMBK] remove old backup complete
[2025-07-13 06:16:06][INFO] [LOCK] release lock @ /tmp/backup.lock
[2025-07-13 06:16:06][INFO] [DONE] backup procedure complete!
[2025-07-13 06:16:06][INFO] ================================================================
```

备份使用 `lz4` 压缩，您可以使用以下命令解压缩和提取 tarball：

```bash
mkdir -p /tmp/data   # 将备份提取到此目录
cat /pg/backup/backup_pg-meta_20250713.tar.lz4 | unlz4 -d -c | tar -xC /tmp/data
```

### 逻辑备份 {#logical-backup}

您也可以使用 `pg_dump` 命令执行逻辑备份。

逻辑备份不能用于 PITR（时间点恢复），
但它们对于在不同主版本之间迁移数据或实现灵活的数据导出逻辑很有用。


### 从仓库引导 {#bootstrap-from-repo}

现在假设您有一个现有集群 `pg-meta`，并且想要**分叉**它作为 `pg-meta2`：

您需要创建新的 `pg-meta2` 集群分叉，然后在其上运行 `pitr`。
