# 管理 PostgreSQL 数据库集群

> 创建/销毁 PostgreSQL 集群，以及对现有集群进行扩容，缩容，克隆集群。

---

LLMS 索引： [llms.txt](/zh/llms.txt)

---

## 速查手册

| 操作                  | 快捷命令                          | 说明                 |
|:--------------------|:------------------------------|:-------------------|
| [**创建集群**](#创建集群)   | `bin/pgsql-add <cls>`         | 创建新的 PostgreSQL 集群 |
| [**扩容集群**](#扩容集群)   | `bin/pgsql-add <cls> <ip...>` | 为现有集群添加从库副本        |
| [**缩容集群**](#缩容集群)   | `bin/pgsql-rm <cls> <ip...>`  | 从集群中移除指定实例         |
| [**销毁集群**](#销毁集群)   | `bin/pgsql-rm <cls>`          | 销毁整个 PostgreSQL 集群 |
| [**刷新服务**](#刷新服务)   | `bin/pgsql-svc <cls> [ip...]` | 重载集群的负载均衡配置        |
| [**刷新HBA**](#刷新hba) | `bin/pgsql-hba <cls> [ip...]` | 重载集群的 HBA 访问规则     |
| [**克隆集群**](#克隆集群)   | -                             | 通过备份集群或 PITR 克隆    |
{.full-width}

其他管理任务，请参考：[**高可用管理**](/docs/pgsql/admin/patroni)，[**管理用户**](/docs/pgsql/admin/user/)，[**管理数据库**](/docs/pgsql/admin/db/)。


----------------

## 创建集群

要创建一个新的 PostgreSQL 集群，请首先在 [**配置清单**](/docs/concept/iac/inventory) 中 [**定义集群**](/docs/pgsql/config/cluster)，然后 [**纳管节点**](/docs/node/admin#添加节点) 并进行初始化：

```bash {tab="脚本" group="tab1-tab2-tab3" value="tab1"}
bin/node-add  <cls>     # 添加分组 <cls> 下的节点
```

```bash {tab="剧本" value="tab2"}
./node.yml  -l <cls>    # 直接使用 Ansible 剧本添加分组 <cls> 下的节点
```

```bash {tab="示例" value="tab3"}
bin/node-add pg-test    # 例子，添加 pg-test 分组下的节点，实际执行 ./node.yml -l pg-test
```

在被纳管的节点上，可以使用以下命令创建集群：（针对 **`<cls>`** 分组执行 [**`pgsql.yml`**](/docs/pgsql/playbook#pgsqlyml) 剧本）

```bash {tab="脚本" group="tab1-tab2-tab3" value="tab1"}
bin/pgsql-add <cls>     # 创建 PostgreSQL 集群 <cls>
```

```bash {tab="剧本" value="tab2"}
./pgsql.yml -l <cls>    # 直接使用 Ansible 剧本创建 PostgreSQL 集群 <cls>
```

```bash {tab="示例" value="tab3"}
bin/pgsql-add pg-test   # 例子，创建 pg-test 集群
```


**示例：创建三节点 PG 集群 `pg-test`**

<div id="td-asciinema-153a0395bbfc7a578746330248f65541-0" class="td-asciinema td-max-width-on-larger-screens" data-td-asciinema
  data-td-timer-label="播放时间">
  <div class="td-asciinema__chrome">
    <span class="td-asciinema__lights" aria-hidden="true"><i></i><i></i><i></i></span>
    <span class="td-asciinema__title" dir="auto">demo/pgsql.cast</span>
  </div>
  <div data-td-asciinema-player></div>
  <script type="application/json" data-td-asciinema-config>{"options":{"autoPlay":true,"fit":"width","loop":true,"markers":[4,"执行"],"preload":false,"speed":1.3,"startAt":0},"src":"/demo/pgsql.cast","theme":"auto"}</script>
</div>


> [!WARNING] 针对已经存在的集群重新执行创建存在风险
> 如果您在已经存在的集群上重新执行创建操作，Pigsty 不会移除已有的数据文件，但现有服务配置会被覆盖，集群会发生 **重启**！
> 此外，如果你在 [**数据库定义**](/docs/pgsql/config/db#baseline) 中指定了 `baseline` SQL，它也会重新执行，如果里面包含删除/覆盖逻辑，可能会导致 **数据丢失**。







----------------

## 扩容集群

若要将新从库添加到 **现有的 PostgreSQL 集群** 中，您需要将 [**实例定义**](/docs/pgsql/config/cluster) 添加到 [**配置清单**](/docs/concept/iac/inventory)：`all.children.<cls>.hosts` 中。

```yaml
pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary } # 已存在的成员
    10.10.10.12: { pg_seq: 2, pg_role: replica } # 已存在的成员
    10.10.10.13: { pg_seq: 3, pg_role: replica } # <--- 新成员
  vars: { pg_cluster: pg-test }
```

扩容集群的操作与 [**创建集群**](#创建集群) 非常类似，首先需要将扩容的节点纳入 Pigsty 管理：[**添加节点**](/docs/node/admin#添加节点)：

```bash {tab="脚本" group="tab1-tab2-tab3" value="tab1"}
bin/node-add <ip>       # 添加 IP 地址为 <ip> 的节点
```

```bash {tab="剧本" value="tab2"}
./node.yml -l <ip>      # 直接使用 Ansible 剧本添加 <ip> 对应的节点
```

```bash {tab="示例" value="tab3"}
bin/node-add 10.10.10.13    # 例子，添加 IP 为 10.10.10.13 的节点，实际执行 ./node.yml -l 10.10.10.13
```

然后在新节点上运行以下命令以扩容集群（针对新节点安装 [**PGSQL 模块**](/docs/pgsql)，使用与现有集群相同的 [**`pg_cluster`**](/docs/pgsql/param#pg_cluster)）

```bash {tab="脚本" group="tab1-tab2-tab3" value="tab1"}
bin/pgsql-add <cls> <ip>  # 添加 IP 地址为 <ip> 的节点
```

```bash {tab="剧本" value="tab2"}
./pgsql.yml -l <ip>       # 核心逻辑：使用 Ansible 剧本在 <ip> 节点上安装 PGSQL 模块
```

```bash {tab="示例" value="tab3"}
bin/pgsql-add pg-test 10.10.10.13   # 示例，为 pg-test 集群扩容 IP 为 10.10.10.13 的节点
```

扩容完成后，您应当 [**刷新服务**](/docs/pgsql/admin/cluster#刷新服务) 以将新成员添加至负载均衡器中以实际承载流量。

**示例：为两节点集群 `pg-test` 扩容一个新从库 `10.10.10.13`**

<div id="td-asciinema-153a0395bbfc7a578746330248f65541-1" class="td-asciinema td-max-width-on-larger-screens" data-td-asciinema
  data-td-timer-label="播放时间">
  <div class="td-asciinema__chrome">
    <span class="td-asciinema__lights" aria-hidden="true"><i></i><i></i><i></i></span>
    <span class="td-asciinema__title" dir="auto">demo/pgsql-append.cast</span>
  </div>
  <div data-td-asciinema-player></div>
  <script type="application/json" data-td-asciinema-config>{"options":{"autoPlay":true,"fit":"width","loop":true,"preload":false,"speed":1.2,"startAt":0},"src":"/demo/pgsql-append.cast","theme":"auto"}</script>
</div>







----------------

## 缩容集群

若要从 **现有的 PostgreSQL 集群** 中移除副本，您需要从 [**配置清单**](/docs/concept/iac/inventory) 的 `all.children.<cls>.hosts` 中移除对应的 [**实例定义**](/docs/pgsql/config/cluster)。

缩容会停止实例并默认删除其数据目录。操作前先执行 `pig pg list <cls>` 与 `pig pb info`，确认目标不是主库、存在近期可恢复备份，
并让操作者输入精确的 `<ip>`，确认后方可实际执行。

缩容集群首先需要卸载目标节点上的 PGSQL 模块（针对 **`<ip>`** 执行 [**`pgsql-rm.yml`**](/docs/pgsql/playbook#pgsql-rmyml) 剧本）：

```bash {tab="脚本" group="tab1-tab2-tab3" value="tab1"}
bin/pgsql-rm <cls> <ip>   # 从集群 <cls> 中移除 <ip> 节点上的 PostgreSQL 实例
```

```bash {tab="剧本" value="tab2"}
./pgsql-rm.yml -l <ip>    # 直接使用 Ansible 剧本移除 <ip> 节点上的 PostgreSQL 实例
```

```bash {tab="示例" value="tab3"}
bin/pgsql-rm pg-test 10.10.10.13  # 例子，从 pg-test 集群移除 10.10.10.13 节点
```

移除 PGSQL 模块后，您可以选择将节点从 Pigsty 管理中移除：[**移除节点**](/docs/node/admin#移除节点)（可选）：

```bash {tab="脚本" group="tab1-tab2-tab3" value="tab1"}
bin/node-rm <ip>          # 从 Pigsty 管理中移除 <ip> 节点
```

```bash {tab="剧本" value="tab2"}
./node-rm.yml -l <ip>     # 直接使用 Ansible 剧本从 Pigsty 管理中移除 <ip> 节点
```

```bash {tab="示例" value="tab3"}
bin/node-rm 10.10.10.13   # 例子，从 Pigsty 管理中移除 10.10.10.13 节点
```

缩容完成后，您应当从 [**配置清单**](/docs/concept/iac/inventory) 中移除该实例的定义，然后 [**刷新服务**](/docs/pgsql/admin/cluster#刷新服务) 以将它从负载均衡器中踢除。

```yaml
pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: replica }
    10.10.10.13: { pg_seq: 3, pg_role: replica } # <--- 执行后移除此行
  vars: { pg_cluster: pg-test }
```

**示例：从三节点集群 `pg-test` 中缩容一个从库 `10.10.10.13`**

<div id="td-asciinema-153a0395bbfc7a578746330248f65541-2" class="td-asciinema td-max-width-on-larger-screens" data-td-asciinema
  data-td-timer-label="播放时间">
  <div class="td-asciinema__chrome">
    <span class="td-asciinema__lights" aria-hidden="true"><i></i><i></i><i></i></span>
    <span class="td-asciinema__title" dir="auto">demo/pgsql-shrink.cast</span>
  </div>
  <div data-td-asciinema-player></div>
  <script type="application/json" data-td-asciinema-config>{"options":{"autoPlay":true,"fit":"width","loop":true,"preload":false,"speed":1.2,"startAt":0},"src":"/demo/pgsql-shrink.cast","theme":"auto"}</script>
</div>








----------------

## 销毁集群

销毁集群需要在集群的所有节点上卸载 PGSQL 模块（针对 **`<cls>`** 执行 [**`pgsql-rm.yml`**](/docs/pgsql/playbook#pgsql-rmyml) 剧本）：

这是不可逆的数据删除：先用 `pig pg list <cls>` 与 `pig pb info` 核对状态和近期备份，决定是否保留独立备份副本，
并要求操作者输入精确集群名。下面命令会直接执行相应的销毁操作。

```bash {tab="脚本" group="tab1-tab2-tab3" value="tab1"}
bin/pgsql-rm <cls>        # 销毁整个 PostgreSQL 集群 <cls>
```

```bash {tab="剧本" value="tab2"}
./pgsql-rm.yml -l <cls>   # 直接使用 Ansible 剧本销毁整个 PostgreSQL 集群 <cls>
```

```bash {tab="示例" value="tab3"}
bin/pgsql-rm pg-test      # 例子，销毁 pg-test 集群
```

销毁 PGSQL 模块后，您可以选择将节点一并从 Pigsty 管理中移除：[**移除节点**](/docs/node/admin#移除节点)（可选，如果还有其他服务可以保留）：

```bash {tab="脚本" group="tab1-tab2-tab3" value="tab1"}
bin/node-rm <cls>         # 从 Pigsty 管理中移除 <cls> 分组下的所有节点
```

```bash {tab="剧本" value="tab2"}
./node-rm.yml -l <cls>    # 直接使用 Ansible 剧本从 Pigsty 管理中移除 <cls> 分组下的所有节点
```

```bash {tab="示例" value="tab3"}
bin/node-rm pg-test       # 例子，从 Pigsty 管理中移除 pg-test 分组下的所有节点
```

销毁结束后，建议及时从 [**配置清单**](/docs/concept/iac/inventory) 中移除整个 [**集群定义**](/docs/pgsql/config/cluster)。

```yaml
pg-test: # 清理这个集群定义分组
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: replica }
    10.10.10.13: { pg_seq: 3, pg_role: replica }
  vars: { pg_cluster: pg-test }
```


**示例：销毁三节点 PG 集群 `pg-test`**

<div id="td-asciinema-153a0395bbfc7a578746330248f65541-3" class="td-asciinema td-max-width-on-larger-screens" data-td-asciinema
  data-td-timer-label="播放时间">
  <div class="td-asciinema__chrome">
    <span class="td-asciinema__lights" aria-hidden="true"><i></i><i></i><i></i></span>
    <span class="td-asciinema__title" dir="auto">demo/pgsql-rm.cast</span>
  </div>
  <div data-td-asciinema-player></div>
  <script type="application/json" data-td-asciinema-config>{"options":{"autoPlay":true,"fit":"width","loop":true,"preload":false,"speed":1.2,"startAt":0},"src":"/demo/pgsql-rm.cast","theme":"auto"}</script>
</div>


注意：如果为这个集群配置了 [**`pg_safeguard`**](/docs/pgsql/param#pg_safeguard)（或全局设置为 `true`），`pgsql-rm.yml` 将中止执行，以避免意外销毁集群。
您可以使用剧本命令行参数明确地覆盖它，以强制执行销毁。
此外默认情况下，集群的备份仓库将同集群一并删除。如果你希望保留备份（例如在使用集中式备份仓库时），可以设置 [**`pg_rm_backup=false`**](/docs/pgsql/param#pg_rm_backup) 参数：


```bash
./pgsql-rm.yml -l pg-meta -e pg_safeguard=false    # 强制销毁受保护的 pg 集群 pg-meta
./pgsql-rm.yml -l pg-meta -e pg_rm_backup=false    # 在销毁集群过程中保留其备份仓库
```








----------------

## 刷新服务

PostgreSQL 集群通过主机节点上的 [**HAProxy**](/docs/concept/arch/pgsql#haproxy) 对外提供 [**服务**](/docs/pgsql/service/)。
当服务定义变化、实例权重变化，或者集群成员发生变化时（例如集群 [**扩容**](#扩容集群) / [**缩容**](#缩容集群)），您需要刷新服务以更新负载均衡器的静态成员配置。默认 Primary/Replica 服务通过 Patroni REST API 健康检查识别当前角色，正常的主从切换或故障转移会自动改道，不要求重新生成 HAProxy 配置。

要在整个集群或特定实例上刷新服务配置（针对 **`<cls>`** 或 **`<ip>`** 执行 [**`pgsql.yml`**](/docs/pgsql/playbook#pgsqlyml) 的 `pg_service` 子任务）：

```bash {tab="脚本" group="tab1-tab2-tab3" value="tab1"}
bin/pgsql-svc <cls>           # 刷新整个集群 <cls> 的服务配置
bin/pgsql-svc <cls> <ip...>   # 刷新集群 <cls> 中指定实例的服务配置
```

```bash {tab="剧本" value="tab2"}
./pgsql.yml -l <cls> -t pg_service -e pg_reload=true        # 刷新整个集群的服务配置
./pgsql.yml -l <ip>  -t pg_service -e pg_reload=true        # 刷新指定实例的服务配置
```

```bash {tab="示例" value="tab3"}
bin/pgsql-svc pg-test                 # 例子，刷新 pg-test 集群的服务配置
bin/pgsql-svc pg-test 10.10.10.13     # 例子，刷新 pg-test 集群中 10.10.10.13 实例的服务配置
```

> 备注：如果您使用集中式的专用负载均衡集群（[**`pg_service_provider`**](/docs/pgsql/param#pg_service_provider)），那么只有刷新集群主库时才会更新负载均衡配置。


**示例：刷新集群 `pg-test` 的服务配置**

<div id="td-asciinema-153a0395bbfc7a578746330248f65541-4" class="td-asciinema td-max-width-on-larger-screens" data-td-asciinema
  data-td-timer-label="播放时间">
  <div class="td-asciinema__chrome">
    <span class="td-asciinema__lights" aria-hidden="true"><i></i><i></i><i></i></span>
    <span class="td-asciinema__title" dir="auto">demo/pgsql-svc.cast</span>
  </div>
  <div data-td-asciinema-player></div>
  <script type="application/json" data-td-asciinema-config>{"options":{"autoPlay":true,"fit":"width","loop":true,"preload":false,"speed":1.2,"startAt":0},"src":"/demo/pgsql-svc.cast","theme":"auto"}</script>
</div>


> [!DETAILS]- 示例：重载 PG 服务以踢除一个实例
> [![asciicast](https://asciinema.org/a/568815.svg)](https://asciinema.org/a/568815)




----------------

## 刷新HBA

当您修改了 HBA 相关配置后，需要刷新 HBA 规则以应用更改。（[**`pg_hba_rules`**](/docs/pgsql/param#pg_hba_rules) / [**`pgb_hba_rules`**](/docs/pgsql/param#pgb_hba_rules)）
如果您有任何特定于清单角色的 HBA 规则，或者在 IP 地址段中引用了集群成员的别名，那么修改 `pg_role` 标签或集群扩缩容后也可能需要刷新 HBA。这里的角色筛选使用静态清单变量，不会随 Patroni 主从切换自动改变。

要在整个集群或特定实例上刷新 PG 和 Pgbouncer 的 HBA 规则（针对 **`<cls>`** 或 **`<ip>`** 执行 [**`pgsql.yml`**](/docs/pgsql/playbook#pgsqlyml) 的 HBA 相关子任务）：

```bash {tab="脚本" group="tab1-tab2-tab3" value="tab1"}
bin/pgsql-hba <cls>           # 刷新整个集群 <cls> 的 HBA 规则
bin/pgsql-hba <cls> <ip...>   # 刷新集群 <cls> 中指定实例的 HBA 规则
```

```bash {tab="剧本" value="tab2"}
./pgsql.yml -l <cls> -t pg_hba,pg_reload,pgbouncer_hba,pgbouncer_reload -e pg_reload=true   # 刷新整个集群
./pgsql.yml -l <ip>  -t pg_hba,pg_reload,pgbouncer_hba,pgbouncer_reload -e pg_reload=true   # 刷新指定实例
```

```bash {tab="示例" value="tab3"}
bin/pgsql-hba pg-test                 # 例子，刷新 pg-test 集群的 HBA 规则
bin/pgsql-hba pg-test 10.10.10.13     # 例子，刷新 pg-test 集群中 10.10.10.13 实例的 HBA 规则
```


**示例：刷新集群 `pg-test` 的 HBA 规则**

<div id="td-asciinema-153a0395bbfc7a578746330248f65541-5" class="td-asciinema td-max-width-on-larger-screens" data-td-asciinema
  data-td-timer-label="播放时间">
  <div class="td-asciinema__chrome">
    <span class="td-asciinema__lights" aria-hidden="true"><i></i><i></i><i></i></span>
    <span class="td-asciinema__title" dir="auto">demo/pgsql-hba.cast</span>
  </div>
  <div data-td-asciinema-player></div>
  <script type="application/json" data-td-asciinema-config>{"options":{"autoPlay":true,"fit":"width","loop":true,"preload":false,"speed":1.2,"startAt":0},"src":"/demo/pgsql-hba.cast","theme":"auto"}</script>
</div>



----------------

## 配置集群

PostgreSQL 的配置参数由 Patroni 管理，初始参数由 [**Patroni 配置模板**](/docs/pgsql/template/) 指定。
集群初始化之后，配置存储在 Etcd 中，并由 Patroni 进行动态管理，并在集群中同步与共享。
Patroni 本身的 [**配置参数**](/docs/pgsql/admin/patroni#修改配置) 大部分可以通过 `patronictl` 命令行工具修改。
其余参数（例如，etcd DCS 配置，日志/RestAPI 等配置）则可以通过下面的子任务进行更新。例如，当 [**etcd**](/docs/etcd) 集群成员发生变动时，你可以刷新 Patroni 配置：

```bash
./pgsql.yml -l pg-test -t pg_conf                   # 更新 Patroni 配置文件
ansible pg-test -b -a 'systemctl reload patroni'    # 重载 Patroni 服务
```

您可以在不同层次上覆盖 Patroni 集中管理的默认，例如单独 [**为实例指定配置参数**](/docs/pgsql/param#pg_parameters)；
单独为 [**为用户指定配置参数**](/docs/pgsql/admin/user)，或者 [**为数据库指定配置参数**](/docs/pgsql/admin/db)。



----------------

## 克隆集群

有两种克隆集群的方式：使用 [**备份集群**](/docs/pgsql/config/cluster#备份集群) 功能，或者使用 [**时间点恢复**](/docs/pgsql/backup/restore#快速上手) 功能。
前者配置简单，无需备份仓库，但需要可达的复制上游，只能克隆指定集群的最新状态；后者依赖集中式的 [**备份仓库**](/docs/pgsql/backup/repository)（例如 Silo），可以克隆到恢复窗口内的任意时间点。

| 方式   | 优点          | 缺点              | 适用场景       |
|:-----|:------------|:----------------|:-----------|
| 备份集群 | 无需备份仓库      | 需要可达上游，只能克隆最新状态 | 灾备，读写分离，迁移 |
| PITR | 可恢复到窗口内任意时点 | 依赖集中式备份仓库       | 误操作恢复，数据审计 |


### 使用备份集群克隆

备份集群（Standby Cluster）通过流复制从上游集群持续同步数据，是克隆集群最简单的方式。
只需在新集群主库上指定 [**`pg_upstream`**](/docs/pgsql/param#pg_upstream) 参数，即可自动从上游集群拉取数据。

```yaml
# pg-test 是原始集群
pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
  vars: { pg_cluster: pg-test }

# pg-test2 是 pg-test 的备份集群（克隆）
pg-test2:
  hosts:
    10.10.10.12: { pg_seq: 1, pg_role: primary, pg_upstream: 10.10.10.11 }  # 指定上游
    10.10.10.13: { pg_seq: 2, pg_role: replica }
  vars: { pg_cluster: pg-test2 }
```

使用以下命令创建备份集群：

```bash {tab="脚本" group="tab1-tab2" value="tab1"}
bin/pgsql-add pg-test2    # 创建备份集群，自动从上游 pg-test 克隆数据
```

```bash {tab="剧本" value="tab2"}
./pgsql.yml -l pg-test2   # 直接使用 Ansible 剧本创建备份集群
```

备份集群会持续追随上游集群，保持数据同步。您可以随时将其 **提升** 为独立集群：

> [!DETAILS]- 示例：提升备份集群为独立集群
> 通过 [**配置集群**](#配置集群) 擦除 `standby_cluster` 配置段，即可将备份集群提升为独立集群：
>
> ```bash
> $ pg edit-config pg-test2
> -standby_cluster:
> -  create_replica_methods:
> -  - basebackup
> -  host: 10.10.10.11
> -  port: 5432
>
> Apply these changes? [y/N]: y
> ```
>
> 提升后，`pg-test2` 将成为可以独立承载写入请求的独立集群，与原集群 `pg-test` 分叉。

> [!DETAILS]- 示例：更改复制上游
> 如果上游集群发生主从切换，您可以通过 [**配置集群**](#配置集群) 更改备份集群的复制上游：
>
> ```bash
> $ pg edit-config pg-test2
>
>  standby_cluster:
>    create_replica_methods:
>    - basebackup
> -  host: 10.10.10.11     # <--- 旧的上游
> +  host: 10.10.10.14     # <--- 新的上游
>    port: 5432
>
> Apply these changes? [y/N]: y
> ```


### 使用 PITR 克隆

[**时间点恢复**](/docs/pgsql/backup/restore)（PITR）允许您将集群恢复到恢复窗口内的任意时间点。
此方式依赖集中式的 [**备份仓库**](/docs/pgsql/backup/repository)（如 Silo/S3），但功能更加强大。

要使用 PITR 克隆集群，在配置中添加 [**`pg_pitr`**](/docs/pgsql/backup/restore#pitr-参数定义) 参数指定恢复目标：

```yaml
# 从 pg-meta 集群的备份克隆一个新集群 pg-meta2
pg-meta2:
  hosts: { 10.10.10.12: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta2
    pg_pitr:
      cluster: pg-meta                    # 从 pg-meta 的备份恢复
      time: '2025-01-10 10:00:00+00'      # 恢复到指定时间点
      archive: false                       # 独立恢复阶段禁用归档
      action: promote                      # 完成重放后提升并启动集群
```

使用 `pgsql-pitr.yml` 剧本执行克隆：

```bash {tab="剧本" group="tab1-tab2" value="tab1"}
./pgsql-pitr.yml -l pg-meta2    # 使用上面显式声明的 action: promote
```

```bash {tab="命令行" value="tab2"}
# 也可以通过命令行参数指定 PITR 选项
./pgsql-pitr.yml -l pg-meta2 -e '{"pg_pitr": {"cluster": "pg-meta", "time": "2025-01-10 10:00:00+00", "archive": false, "action": "promote"}}'
```

PITR 支持多种恢复目标类型：

| 目标类型  | 参数示例                             | 说明           |
|:------|:---------------------------------|:-------------|
| 时间点   | `time: "2025-01-10 10:00:00+00"` | 恢复到指定时间戳     |
| 事务 ID | `xid: "250000"`                  | 恢复到指定事务之前/之后 |
| 恢复点   | `name: "before_migration"`       | 恢复到命名恢复点     |
| LSN   | `lsn: "0/4001C80"`               | 恢复到指定 WAL 位置 |
| 最新    | `pg_pitr: {}`                    | 恢复到 WAL 归档末尾 |

> [!NOTE] PITR 恢复后处理
> 跨集群恢复完成后，按 [**克隆善后**](/docs/pgsql/backup/cluster/#克隆善后) 处理归档与 stanza。

更多 PITR 的详细用法，请参考 [**恢复操作**](/docs/pgsql/backup/restore)；跨集群恢复后的归档与 stanza 处理见 [**克隆数据库集群**](/docs/pgsql/backup/cluster/)。
