PostgreSQL 备份恢复策略pg_basebackup、WAL 归档与 PITR 在企业 Java 系统中的落地1. 先看一个真实场景备份文件在但业务回不来凌晨两点一个订单系统的 DBA 被电话叫醒有人执行了一条没有 WHERE 条件的 UPDATE把orders表的status全部改成了CANCELED。运维的第一反应通常是“我们每天凌晨 2 点都有全量备份恢复它就行”。可当真的开始恢复时问题一个接一个冒出来全量备份是 20 小时前的恢复它意味着丢掉这 20 小时内所有新订单业务无法接受。备份脚本只验证了“文件生成成功”没人验证过“这些文件能恢复成可用实例”。数据库开启了归档但归档目录一周前就因为磁盘写满而停止接收新的 WAL没人发现。恢复出来的实例没有做时间点控制只能回到备份那一刻不能回到误操作前 1 秒。这个场景说明了一件事备份的价值不在于“备份动作成功”而在于“在限定时间内、把数据恢复到限定的状态”。企业里的备份恢复本质是在回答三个问题能恢复到哪个时间点恢复要花多久恢复出来的数据对不对本文围绕 PostgreSQL 的三件核心工具展开pg_basebackup负责拿到一份可信的全量基线WAL 归档负责记录基线之后的所有变更PITRPoint-In-Time Recovery时间点恢复负责把基线加变更重放到你指定的那个瞬间。三者缺一不可只堆其中任何一个都无法形成闭环。2. 一句话模型与全局框架先用一句普通中文给出核心模型先做一份数据库的“全量照片”再持续记录照片之后的每一次改动恢复时把照片按顺序叠加改动直到停在你要的那一刻。全量照片是pg_basebackup的产物改动记录是归档的 WAL叠加过程就是 PITR。把整体拆成四个部分来看它们的关系可以用一条链路串起来[业务写入] -- [PostgreSQL 主库] | | 1. 全量物理拷贝 (pg_basebackup) v [基础备份目录 base.tar.gz] | | 2. 持续归档 (archive_command) v [WAL 归档目录 / 对象存储] | | 3. 恢复时重放 (recovery_target_time) v [恢复到指定时间点的新实例] -- [校验] -- [切流]这四个部分分别对应四类角色主库产生数据与 WAL备份工具负责在某个时刻抓取数据文件的一致性快照归档通道把 WAL 从主库搬运到独立存储恢复流程把基线和解归档 WAL 组装成一个可用实例。一次正常的恢复会按这个顺序走先在生产之外准备一台机器把基础备份解压放好写好restore_command指向归档目录在postgresql.conf或postgresql.auto.conf里指定恢复目标启动实例PostgreSQL 会先重放基础备份里自带的 WAL再从归档里拉取后续 WAL一路重放到目标点最后把实例提升为可写。这里最容易误解的是基础备份并不是“整个数据库目录的冷拷贝”。如果直接cp -r数据目录你很可能拷到一个不一致的状态比如数据页已经改了但对应的 WAL 还没落盘。pg_basebackup的价值就在于它通过 PostgreSQL 的复制协议在数据库运行时抓取一个一致性的快照。3. pg_basebackup拿到一份可信的全量基线3.1 它解决什么问题pg_basebackup是 PostgreSQL 自带的物理备份工具它通过流复制协议从主库读取整个数据目录和必要的 WAL生成一份可以直接用于恢复的基础备份。它不做逻辑导出不解析 SQL只搬运物理文件和事务日志。它适合的场景是你需要一份和主库二进制一致、可以配合 WAL 归档做 PITR 的基线。它不适合的场景是你只想导出某几张表、需要跨大版本迁移、或者需要恢复到架构不同的库那些属于pg_dump/pg_dumpall的领域。备份方式上pg_basebackup支持两种模式plain 模式把文件直接写到目标目录得到的是一个和主库布局相同的可启动目录。tar 模式把数据打包成base.tar和若干pg_wal.tar适合传输到对象存储或做异地归档。3.2 一个完整的最小示例目标在本地把一台 PostgreSQL 16 主库完整备份到/backup/base并且带上后续 PITR 需要的 WAL。前置环境主库运行在 5432 端口有一个具备REPLICATION权限的用户repl密码放在.pgpass或环境变量里。# 前置检查确认主库允许复制连接并且归档已开启psql-h127.0.0.1-p5432-Upostgres-cSHOW wal_level;psql-h127.0.0.1-p5432-Upostgres-cSHOW archive_mode;psql-h127.0.0.1-p5432-Upostgres-cSHOW archive_command;# 执行物理基础备份plain 模式写入 /backup/base附带 WALmkdir-p/backup/base pg_basebackup\-h127.0.0.1-p5432-Urepl\-D/backup/base\-Fp\-Xs\-P\-R\-cfast# 查看结果ls-lh/backup/basecat/backup/base/backup_labelcat/backup/base/postgresql.auto.conf参数说明它们各自在链路中的位置-Fp表示 plain 格式直接得到可启动目录-Xs表示把备份期间产生的 WAL 一并打包进去这样恢复时不必依赖外部归档就能先追平到备份结束点-P显示进度-R会在目标目录生成standby.signal和primary_conninfo适合直接当流复制备库用-c fast触发一次快速检查点缩短备份时间。预期结果/backup/base下出现完整的PG_VERSION、base/、global/、pg_wal/等目录backup_label记录了备份的起始 WAL 位点这是后续 PITR 的起点。容易改错的地方忘记-Xs导致备份期间的 WAL 不在备份里恢复时必须依赖外部归档用 root 执行导致目标目录属主是 rootPostgreSQL 启动时报权限错误主库wal_level是minimal这样根本无法做归档和 PITR。3.3 生产上的取舍plain 模式简单直接但备份过程中目标目录不能是主库正在使用的目录tar 模式更适合做异地传输和压缩归档。如果你的数据量在几百 GB 以上还可以考虑pg_basebackup配合--compress或外部的pgBackRest/Barman它们在大规模增量备份、保留策略、对象存储集成上更成熟。pg_basebackup是单线程流式读取备份时长近似和数据库大小成正比。对 TB 级库每次全量都可能压垮网络和 IO所以生产上更常见的是“周期性全量 持续 WAL 归档”而不是每次恢复都从头全量。4. WAL 归档把每次改动安全地搬出主库4.1 WAL 是什么、为什么要归档WALWrite-Ahead Log预写式日志是 PostgreSQL 保证崩溃一致性和复制的基础。任何数据页修改前对应的日志必须先落盘。WAL 本身是循环使用的写完一个段默认 16MB后如果不再需要就会被覆盖。要让 PITR 成为可能就必须在 WAL 段被覆盖之前把它们复制到主库之外的存储上这就是归档。归档解决了两个问题一是让备份之后的变更不再丢失二是让恢复能沿着时间轴往前走。没有归档的备份只能恢复到备份结束那一刻。归档的核心配置在postgresql.conf中下面给出一个可复现的最小配置# postgresql.conf 片段开启 WAL 归档 wal_level replica # 至少要 replicaPITR 需要它 archive_mode on # 打开归档开关 archive_command test ! -f /archive/%f cp %p /archive/%f archive_timeout 60 # 最多 60 秒强制切换一次缩短恢复窗口archive_command的语义非常重要它必须满足“文件已经存在就不要覆盖成功返回 0失败返回非 0”。%p是主库上的 WAL 路径%f是文件名。PostgreSQL 会不断重试同一条命令直到它返回 0然后才允许覆盖本地 WAL。这意味着如果归档目录不可写主库的pg_wal会逐渐涨满最终导致写入失败。4.2 一个可观测的归档脚本示例生产环境不建议用裸cp因为它没有错误上报、没有校验、没有分级存储。下面是一个更贴近生产的归档脚本示例目标是归档到一个按日期分目录的存储并在失败时留下可排查的日志。#!/usr/bin/env bash# /usr/local/bin/pg_archive.sh# 输入%p 主库 WAL 路径%f WAL 文件名set-euopipefailWAL_PATH$1WAL_NAME$2ARCHIVE_ROOT/archive/pgDAY_DIR${ARCHIVE_ROOT}/$(date%Y%m%d)TARGET${DAY_DIR}/${WAL_NAME}mkdir-p${DAY_DIR}# 幂等已存在则直接成功退出if[-f${TARGET}];thenexit0ficp${WAL_PATH}${TARGET}.tmp# 用 sha256 保证搬运过程没有损坏sha256sum${TARGET}.tmp${TARGET}.tmp.sha256mv${TARGET}.tmp${TARGET}echo$(date-Iseconds)archived${WAL_NAME}${ARCHIVE_ROOT}/archive.logexit0在postgresql.conf中把archive_command指向它archive_command /usr/local/bin/pg_archive.sh %p %f关键步骤和结果每次 WAL 切换时脚本把段文件复制到以日期命名的目录里同时生成校验文件。test ! -f或脚本里的存在性判断保证了幂等重复调用不会破坏已有文件。失败时脚本返回非 0PostgreSQL 会保留本地 WAL 并持续重试。边界和常见错误归档目录和主库必须在不同物理盘或不同机器上否则一盘损坏会同时带走数据文件和归档脚本必须有超时控制否则一次网络卡顿会让 WAL 堆积archive_mode从off改成on需要重启从on改成always只需 reload这些版本相关行为要以官方文档为准。4.3 归档监控不要只看“有没有报错”归档失败往往是静默的。archive_command失败不一定立刻让业务报错它只是让 WAL 堆积。可以在主库上周期性检查-- 查看归档统计成功数、失败数、最后一次归档的 WALSELECTarchived_count,failed_count,last_archived_wal,last_archived_time,last_failed_wal,last_failed_timeFROMpg_stat_archiver;如果failed_count持续增长或者last_archived_time距离现在超过archive_timeout的若干倍就要告警。还有一个更直接的信号pg_wal目录里累积的段数量持续上升说明旧 WAL 一直没被归档成功释放。5. PITR把基线和高频变更重放到指定瞬间5.1 一句话理解 PITR 的状态流转可以把 PITR 理解成“在一台新机器上重演历史”先把基础备份铺开然后让 PostgreSQL 从备份结束点开始按顺序读取归档 WAL一条条重放直到重放到你指定的时间点、事务 ID 或恢复点名称最后停下并允许写入。整体状态流转如下[基础备份目录] --启动-- [进入恢复模式 crash recovery] | | restore_command 拉取归档 WAL v [持续重放 WAL] --到达 recovery_target_time-- [一致性停止点] | | pg_ctl promote 或 recovery_target_action 触发 v [实例变为可写] -- [校验业务数据]5.2 一个完整的 PITR 恢复示例目标把备份/backup/base和归档/archive/pg恢复成一台新实例恢复到 2024-06-01 10:30:00 之前的状态模拟“误删数据前 1 分钟”。前置环境已安装同版本 PostgreSQL 16新实例数据目录/var/lib/pgsql/16/data端口 5433避免和生产冲突。# 1. 停止目标实例清空数据目录pg_ctl-D/var/lib/pgsql/16/data stop-mfast||truerm-rf/var/lib/pgsql/16/data/*# 2. 拷贝基础备份plain 模式下直接复制文件cp-a/backup/base/. /var/lib/pgsql/16/data/chown-Rpostgres:postgres /var/lib/pgsql/16/datachmod700/var/lib/pgsql/16/data# 3. 指定恢复命令和恢复目标cat/var/lib/pgsql/16/data/postgresql.auto.confEOF restore_command cp /archive/pg/20240601/%f %p recovery_target_time 2024-06-01 10:30:0008 recovery_target_action promote EOF# 4. 触发恢复sudo-upostgres pg_ctl-D/var/lib/pgsql/16/data start# 5. 观察日志确认重放到目标点并提升tail-f/var/lib/pgsql/16/data/log/postgresql-*.log预期结果日志里会看到restored log file 0000000100000000000000A1 from archive、recovery stopping before commit of transaction ...、database system is ready to accept connections。启动后实例可写SELECT pg_is_in_recovery();返回f。关键步骤说明restore_command的作用和archive_command对称负责把归档 WAL 拉回本地recovery_target_time决定停在哪里recovery_target_action promote表示到达目标后自动提升。如果只想恢复到一致性点并保持只读做校验可以用pause手动检查后再 promote。容易改错的地方归档目录里没有备份结束点之后的 WAL恢复会停在一个较早的位置recovery_target_time时区写错导致恢复点偏差几小时用cp /archive/pg/%f这种不带日期目录的路径因为归档按日期分区而找不到文件。5.3 恢复目标怎么选PITR 支持多种恢复目标选择哪种取决于你要“精确回到某个瞬间”还是“回到某个逻辑检查点”恢复目标参数含义典型场景注意点recovery_target_time恢复到指定时间戳误操作前 1 分钟依赖时间准确性事务提交时间可能存在边界模糊recovery_target_xid恢复到指定事务 ID已知误操作事务号需要先从事务日志或审计里定位 xidrecovery_target_lsn恢复到指定 WAL 位点精确到字节级LSN 不易人工获取适合工具驱动recovery_target_name恢复到已创建的恢复点变更窗口前后打点需要在正常运行时提前pg_create_restore_pointrecovery_target恢复到最近的一致性点只要求可用不要求精确得到的是备份结束点或最近可恢复点对企业 Java 系统来说最常见的组合是在发布前用pg_create_restore_point打一个命名恢复点配合recovery_target_name做发布回滚遇到人为误操作用recovery_target_time精确回退。6. 恢复窗口、RPO 与 RTO 怎么算6.1 三个时间概念备份恢复不能只看“有没有备份”要看三个时间量RPORecovery Point Objective恢复点目标最多能容忍丢多少数据通常表现为时间。RTORecovery Time Objective恢复时间目标最多能容忍业务中断多久。恢复窗口从决定恢复到实例可用这段过程实际花的时间由“找备份 解压 重放 WAL 校验 切流”组成。它们的关系可以用下面的式子近似表达可恢复的最早时间点 基础备份开始时刻 可恢复的最晚时间点 最后一个成功归档的 WAL 时刻 实际 RPO 当前时间 - 可恢复的最晚时间点 RTO ≈ 备份加载时间 WAL 重放时间 校验与切流时间这意味着即使你做了一次全量如果没有持续归档可恢复的最晚时间点会一直停在备份结束点RPO 会随时间无限变大。archive_timeout越小RPO 上限越小但归档频率越高、存储和网络压力越大。6.2 数字例子假设数据库 200GBpg_basebackup速率 100MB/s那么仅拷贝基础备份就要约 34 分钟。若每小时产生 2GB WAL恢复到 3 小时前需要重放约 6GB WAL在恢复机器上重放速率约 50MB/s则需要约 2 分钟。再叠加 5 分钟校验与切流RTO 大约 40 分钟。如果你的业务要求 RTO 小于 15 分钟这个方案就不达标需要考虑流复制备库做故障切换PITR 只作为“回到过去某点”的手段。这个例子的意义是RTO 不是备份工具单点决定的而是整条链路的最慢环节决定的。常见的瓶颈是基础备份太大、WAL 重放太慢、恢复机器磁盘 IO 弱、校验和切流没有自动化。7. 恢复之后备份校验与演练7.1 三类校验“备份成功”和“备份可用”是两件事。工程上至少要做三类校验文件级校验备份文件是否完整、能否解压、校验和是否匹配。pg_basebackup的backup_label和pg_verifybackup可以帮你检查基础备份的完整性。可启动校验把备份恢复成一台临时实例确认能启动、能连接、SELECT正常。业务级校验对关键表做行数、聚合值或抽样比对确认恢复出来的数据业务上可用。下面是一个可以周期性运行的校验脚本示例目标是验证基础备份的完整性#!/usr/bin/env bash# /usr/local/bin/verify_backup.sh# 输入备份目录如 /backup/baseset-euopipefailBACKUP_DIR$1# 1. 目录是否存在且包含 backup_labeltest-f${BACKUP_DIR}/backup_labelechobackup_label found:cat${BACKUP_DIR}/backup_label# 2. 使用 pg_verifybackup 校验备份完整性pg_verifybackup${BACKUP_DIR}# 3. 检查是否存在 PostgreSQL 版本文件test-f${BACKUP_DIR}/PG_VERSIONechoPG_VERSION$(cat${BACKUP_DIR}/PG_VERSION)echoverify ok:${BACKUP_DIR}执行结果pg_verifybackup会输出每个文件的校验结果如有缺失会返回非 0。这个脚本可以放进监控每周跑一次并告警。7.2 业务级校验的 SQL 示例目标在恢复出的临时实例上确认订单表的关键指标和生产某个历史时点一致。前置环境已启动恢复实例端口 5433。-- 在恢复实例上执行检查订单总数与状态分布SELECTstatus,count(*)AScntFROMordersGROUPBYstatusORDERBYstatus;-- 检查最近 1 小时的订单是否存在用于判断恢复点是否到位SELECTcount(*)ASrecent_ordersFROMordersWHEREcreated_atnow()-interval1 hour;-- 检查关键表的行数SELECTrelname,n_live_tupFROMpg_stat_user_tablesWHERErelnameIN(orders,order_items,payments);结果解读如果recent_orders为 0说明恢复点过于靠前如果状态分布异常例如全部是CANCELED说明恢复点停在了误操作之后。这些检查应写进恢复演练的 checklist而不是靠人工临时判断。8. 和 Spring Boot 应用怎么衔接8.1 应用侧的配置要点对 Spring Boot 应用来说备份恢复不是应用直接调用的功能但应用侧的配置会直接影响恢复质量。两个关键点连接串要能指向恢复实例写入要能快速切走。下面是一个application.yml示例目标是把数据库地址、连接池和故障切换解耦便于恢复时改指向临时实例spring:datasource:url:jdbc:postgresql://db-primary.internal:5432/orderdb?targetServerTypeprimaryusername:order_apppassword:${DB_PASSWORD}hikari:maximum-pool-size:20connection-timeout:3000validation-timeout:1000keepalive-time:30000management:health:db:enabled:truetargetServerTypeprimary让 JDBC 驱动在多主机场景下优先选择主库connection-timeout和validation-timeout让故障实例被快速识别而不是长时间挂起。恢复期间运维把域名db-primary.internal指向恢复实例即可应用无需改代码。8.2 一个用于恢复前“冻结写入”的最小 Spring Boot 示例目标在决定恢复前先让应用停止写入避免恢复出来的数据和正在跑的实例继续分叉。前置环境Spring Boot 3.x Spring Data JPA数据库为 PostgreSQL。packagecom.example.backup;importorg.springframework.boot.actuate.health.Health;importorg.springframework.boot.actuate.health.HealthIndicator;importorg.springframework.jdbc.core.JdbcTemplate;importorg.springframework.stereotype.Component;importjava.util.concurrent.atomic.AtomicBoolean;/** * 恢复窗口期间用于控制写入的开关。 * 生产上通常由运维通过配置中心或发布系统触发。 */ComponentpublicclassWriteGateimplementsHealthIndicator{privatefinalAtomicBooleanwritesEnablednewAtomicBoolean(true);privatefinalJdbcTemplatejdbcTemplate;publicWriteGate(JdbcTemplatejdbcTemplate){this.jdbcTemplatejdbcTemplate;}/** * 冻结写入前确认当前实例可连接并记录一个用于对账的 LSN。 * 返回的 LSN 可以作为后续恢复目标或校验参考。 */publicStringfreezeWrites(){writesEnabled.set(false);StringlsnjdbcTemplate.queryForObject(SELECT pg_current_wal_lsn()::text,String.class);returnlsn;}publicvoidresumeWrites(){writesEnabled.set(true);}publicbooleanisWritesEnabled(){returnwritesEnabled.get();}OverridepublicHealthhealth(){if(writesEnabled.get()){returnHealth.up().withDetail(writes,enabled).build();}returnHealth.outOfService().withDetail(writes,frozen).build();}}关键步骤说明freezeWrites()把写入开关置为关闭并读取当前 WAL 位点健康检查返回OUT_OF_SERVICE方便负载均衡把流量摘走。恢复完成后调用resumeWrites()恢复写入。适用场景与边界这个示例只演示了“冻结开关”的思路真实系统需要在业务写入入口如 Service 层或拦截器真正检查这个开关否则只是改了一个无人读取的变量。pg_current_wal_lsn()返回的是当前写入位点可以作为恢复后的对账参考但不能直接当作 PITR 目标因为 PITR 目标通常由归档侧的时间点决定。9. 常见误区9.1 把 pg_dump 当 PITR 的基础pg_dump是逻辑备份得到的是 SQL 或自定义格式的数据快照不包含物理层面的 WAL。它适合迁移、单表导出、跨版本升级但不能配合 WAL 归档做时间点恢复。想做 PITR起点必须是物理基础备份。9.2 以为“备份成功就是可恢复”备份脚本返回 0 只说明文件写出去了。文件是否完整、能否启动、数据是否一致需要单独的校验环节。没有恢复演练的备份和没有备份差别不大。9.3 归档目录和主库放同一块盘这是最危险的配置之一。主库磁盘损坏时数据文件和归档同时丢失PITR 直接失效。归档至少要放到不同机器或对象存储。9.4 忽略 archive_command 的失败重试特性PostgreSQL 会反复重试同一条archive_command并且不会覆盖本地 WAL。如果命令因为权限或路径问题一直失败pg_wal会持续增长最终写满磁盘导致主库不可写。归档失败必须告警。9.5 恢复时忘记摘流恢复实例启动后如果应用连接串还指向它、且它有写入流量可能产生新的分叉数据。恢复期间的正确顺序是先摘流或冻结写入再启动恢复实例校验通过后再切流。10. 生产实践建议基础备份和 WAL 归档必须同时存在。只有基础备份RPO 等于备份间隔只有归档没有基线无法快速重建。给归档目录做容量告警和生命周期管理。WAL 归档量随写入量增长保留策略要覆盖最长的恢复窗口需求。定期做恢复演练。至少每季度一次从备份恢复到一台临时实例验证可启动、可查询、关键指标正确并记录实际 RTO。命名恢复点用于发布回滚。在重要发布前执行pg_create_restore_point(release_20240601)出问题时可以按名称精确恢复。恢复目标和时区写清楚。跨时区团队尤其要统一时区避免恢复到错误的时间点。把恢复步骤脚本化。手工恢复容易漏步骤把拷贝、配置、启动、校验写成脚本降低人为失误。11. 排障清单现象可能原因排查命令或位置恢复后数据停在很早的时点归档缺失或 restore_command 路径错误看pg_stat_archiver、检查归档目录文件恢复日志报找不到 WAL 文件归档未覆盖备份结束点之后的段对比backup_label中的起始位点与归档列表主库写入变慢、pg_wal 膨胀archive_command 持续失败SELECT * FROM pg_stat_archiver;看 failed_count恢复实例无法启动数据目录权限、属主或配置错误检查postgresql.auto.conf、数据目录权限恢复后业务校验不通过恢复目标选错或时区偏差检查recovery_target_time与时区设置恢复耗时远超预期基础备份过大或恢复机器 IO 弱分阶段计时拷贝、解压、重放、校验12. 面试/复盘问题为什么 PITR 必须同时依赖基础备份和 WAL 归档缺少任一会发生什么pg_basebackup的-Xs和-Xf有什么区别分别在什么场景使用archive_command为什么必须幂等失败重试会对主库产生什么影响recovery_target_time和recovery_target_name各自适合什么业务场景如果 RTO 要求小于 15 分钟PITR 和流复制备库各自扮演什么角色如何设计一套“备份是否真的可恢复”的周期性校验机制恢复期间应用侧需要做哪些配合动作为什么不能只靠 DBA 操作13. 总结把知识收回一张决策表回到开头那个凌晨的场景一个成熟的团队应该能在 40 分钟内完成确认恢复目标时间点、在临时机器上铺开基础备份、通过归档 WAL 重放到目标点、启动实例、跑业务校验、切流。要做到这一点靠的不是某个神奇命令而是整条链路都经过了验证。把本文的关键选择收进一张决策表你的目标推荐手段关键配置或命令主要限制回到某个时间点基础备份 WAL 归档 PITRpg_basebackup、archive_command、recovery_target_time依赖归档连续性和恢复演练快速切换故障实例流复制备库 切换primary_conninfo、pg_ctl promote无法回到过去只能接管当前单表或跨版本迁移逻辑备份pg_dump/pg_restore不适合大规模 PITR发布前打点命名恢复点pg_create_restore_point需要在发布前主动执行验证备份可用性文件校验 恢复演练pg_verifybackup、临时实例启动需要额外资源和流程最后记住一句话全量基线让你有起点WAL 归档让你能往前走PITR 让你能停在指定的一刻而校验和演练让你确信这三件事真的成立。14. 参考资料PostgreSQL 官方文档Backup and RestoreBackup and Restore 章节PostgreSQL 官方文档Continuous Archiving and Point-in-Time RecoveryPITRPostgreSQL 官方文档Write-Ahead LoggingWALPostgreSQL 官方文档pg_basebackupPostgreSQL 官方文档pg_verifybackupPostgreSQL 官方文档pg_stat_archiver 视图PostgreSQL 官方文档Recovery Configurationrestore_command、recovery_target_* 参数
阅读完成 · 觉得有帮助?