
1. 为什么需要pg_basebackup物理备份与逻辑备份的本质差异很多刚接触PostgreSQL的开发者最早用的备份命令一定是pg_dump。它的逻辑很简单把表结构、数据以SQL或自定义格式导出需要的时候再导回去。这个工具应付日常迁移、部分表备份完全够用但真到了全库裸奔式恢复或者搭建一个和主库一模一样的从库这种场景pg_dump就会暴露出明显的短板。先讲一个我实际遇到过的情况。某次开发环境需要克隆一个生产库的结构和数据数据量大概200GB我第一反应也还是pg_dump。备份导出了恢复到新实例却一路报错先缺角色、再缺表空间、然后部分序列的当前值不对应用登录直接就崩了。折腾了半个多小时才想起来pg_dump默认导出的是数据对象但全局对象角色、表空间这类得用pg_dumpall或者单独处理而且逻辑导出受事务快照限制并发写多的情况下不同表导出的一致性点根本不是同一个时刻。这就是pg_basebackup存在的理由。它是一个数据库层的物理备份工具直接复制整个数据目录同时通过底层机制保证复制出来的结果是某个时间点的一致快照。它处理的不是哪几张表而是整个实例。两者的本质差异可以这样理解对比维度pg_dump逻辑备份pg_basebackup物理备份备份对象数据库对象表、视图、函数等整个数据目录一致性点每个表各自的时间点整体非一致通过LSN标记整体一致恢复方式执行SQL重新建表导数据直接替换数据目录启动即用是否包含角色/权限默认不含需额外导出包含数据目录里有全局对象是否包含配置文件不包含包含postgresql.conf、pg_hba.conf等是否支持增量支持通过表时间戳或CDC原生不支持需配合WAL归档做增量典型用途迁移单库、备份业务表全实例备份、搭建从库、容灾重建一句话概括如果你要的是一份数据库的完整替身那就用pg_basebackup如果你要的是这张表里的数据留下来做分析pg_dump更合适。2. 备份背后的事LSN、WAL与一致性点用pg_basebackup的时候命令敲起来很简单但理解它为什么可靠比会敲命令更重要。2.1 LSN是什么为什么备份必须记录它LSNLog Sequence Number日志序列号是PostgreSQL内部日志的唯一递增编号可以理解为一盘录像带的时间码。每一次数据页的修改、每一次检查点、每一个事务提交都会在WAL里写一条记录并对应一个LSN。pg_basebackup的一致性原理是这样的备份工具开始执行时会请求数据库进入备份模式此时数据库记录一个起始LSN然后声明从这个点开始所有对数据文件的修改我会同时写入WAL你们放开来备份数据文件就行。备份数据目录的同时WAL也在持续生成保证数据文件复制到一半也没关系因为之后恢复时会用WAL把缺的部分补回来。等数据文件复制完毕备份工具再请求退出备份模式记录结束LSN。从起始LSN到结束LSN之间的所有WAL就是补齐缺口的关键材料。2.2 WAL机制备份和恢复如何靠日志搭桥PostgreSQL的WALWrite-Ahead Logging预写日志机制核心规则是先写日志再写数据文件。任何时候数据库实例崩溃启动时都会读取WAL把尚未落盘的数据页重放一遍术语叫redo。备份恢复走的同样是这套规则。pg_basebackup导出的数据目录里有些数据页可能停留在备份中途的过渡状态没关系只要把备份起始LSN之后的WAL拿过来重放所有数据页就会收敛到完全一致的状态。这也是为什么备份命令里有关于WAL的参数备份过程中产生的WAL要么直接传输到备份目录-X stream要么要求你先开启WAL归档-X fetch配合archive_mode否则备份恢复到一半就会因为缺少日志而彻底不可用。2.3 数据库层备份与文件复制的关系有些场景下DBA图省事直接tar整个数据目录当备份这种做法在实例正常关闭时可以凑合但在运行状态下复制必然导致数据文件内容不一致更别提恢复后可能起不来。pg_basebackup相当于在数据库层帮你封装好了安全复制流程权限校验必须有replication权限一致性标记确保恢复后有准确的LSN起点WAL收集保证日志完整数据目录结构校验避免复制出残缺目录所以别拿手工tar目录去碰运气用pg_basebackup这类官方工具才是正经方案。3. pg_basebackup命令详解从基础参数到搭建从库3.1 最基础用法最常用的一条命令长这样pg_basebackup -h 192.168.1.10 -p 5432 -U replica_user \ -D /backup/pgdata_backup \ -F p -X stream -P -v这条命令的意思从192.168.1.10的5432端口用replica_user用户连接把整个数据目录备份到/backup/pgdata_backup输出格式为普通目录-F p备份过程中的WAL用流复制方式直接传过来-X stream打印进度-P和详细信息-v。备份完成后/backup/pgdata_backup下的内容就是你源库数据目录的一个完整拷贝可以直接拿去做恢复测试也可以当作从库的基础目录。3.2 关键参数分级参数看着多实际使用分四个层级第一层连接参数。-h指定主机-p指定端口-U指定备份用户。需要注意普通超级用户不行必须使用具备replication权限的账号。如果没有先在主库上创建CREATE ROLE replica_user LOGIN REPLICATION PASSWORD your_password;然后在pg_hba.conf里加一条允许该用户以replication方式连接host replication replica_user 192.168.1.0/24 md5改完pg_hba.conf记得reloadpg_ctl reload -D /data/pgdata否则客户端会直接报no pg_hba.conf entry for replication connection。第二层备份内容参数。-D备份目标目录必须为空或不存在但父目录必须存在。这条坑最多后面专门讲。-F输出格式p表示普通目录t表示tar包。做恢复和从库时建议用p方便直接改配置迁移归档时用t更省inode。-XWAL收集方式stream表示备份期间实时流式传输fetch表示备份结束后从归档目录补充要求已开启archive_mode。推荐stream不依赖归档是否配置好。-Z压缩级别配合-F t使用对目录格式无效。第三层一致性标记参数。-R自动写入standby.signal或recovery.conf相关配置这是搭建从库最省事的方式它会在备份目录里生成连接主库所需的primary_conninfo参数。-c备份模式fast表示立即执行快速检查点spread则允许平滑检查点。一般用fast备份耗时会短很多。第四层进阶参数。-C -S slot_name创建并指定复制槽位防止备份期间主库提前清理掉未消费的WAL。单次备份无所谓但要长期保留备份、或担心主库WAL清理速度太快建议用槽位。-n备份结束后不执行pg_stop_backup()适用于手动控制的特殊场景极少用到。-P显示进度建议加上不然长备份期间会以为卡死了。-T指定表空间映射目标机器表空间路径和源库不一致时用。3.3 搭建流复制从库的实战这是pg_basebackup出镜率最高的场景。假设主库在192.168.1.10从库在192.168.1.11目标目录是/data/pgdata操作方法如下在从库机器上确保/data/pgdata为空或不存在rm -rf /data/pgdata执行备份并自动写入复制连接配置pg_basebackup -h 192.168.1.10 -p 5432 -U replica_user \ -D /data/pgdata \ -F p -X stream -R -P -v -c fast启动从库这里假设你用pg_ctlpg_ctl start -D /data/pgdata到主库上验证从库状态SELECT client_addr, state, sync_state FROM pg_stat_replication;正常情况下能看到一行state为streaming。-R参数做了几件事生成standby.signal文件、在postgresql.auto.conf里写入primary_conninfo、配置必要的复制相关参数。也就是说从库启动后会自动连接主库建立流复制全程不需要手动编辑恢复配置对搭建主从是极大的省心项。3.4 时间线、检查点与备份一致性校验备份完成后目录里会有一个backup_label文件它记录着备份的起始时间线ID、起始LSN和检查点位置。恢复时PostgreSQL会依靠这个文件来决定从哪个WAL段开始重放。所以千万不要随手删掉backup_label虽然某些情况下系统能重新生成但人为删除它属于自找麻烦。完整性校验可以这样做备份结束后主库执行pg_switch_wal()切换一个WAL段把备份起始LSN之后的所有WAL段都归档好然后对备份目录做一次离线校验pg_checksums -c -D /backup/pgdata_backup不过pg_checksums要求数据目录完整且校验和开启不是所有环境都默认开了。日常场景更实用的校验方式是恢复后起实例这个放到恢复演练部分细说。4. 恢复演练备份的价值在用起来那一刻很多人把备份做完就归档了从来没验证过一次恢复这是非常危险的。备份文件是否可用、恢复流程要多久、需要哪些额外的WAL文件这些只有实际演练过才知道。4.1 恢复前的准备恢复机器上需要安装同版本小版本最好一致的PostgreSQL然后规划好目录和数据目录mkdir -p /data_restore/pgdata # 清空目标目录 rm -rf /data_restore/pgdata/*把备份目录里的内容恢复到目标位置。如果备份当时用的是目录格式可以直接用cp -a /backup/pgdata_backup/. /data_restore/pgdata/ chown -R postgres:postgres /data_restore/pgdata如果用tar包格式先解压到临时位置mkdir -p /data_restore/tmp tar -xzf base.tar.gz -C /data_restore/tmp # 如果备份时WAL单独打包 tar -xzf pg_wal.tar.gz -C /data_restore/tmp/pg_wal/ mv /data_restore/tmp/* /data_restore/pgdata/4.2 PITR完整流程如果只是恢复到备份瞬间的状态也叫全量恢复把backup_label文件和WAL目录放好直接启动实例即可。但大多数生产恢复需求是恢复到某个指定的时间点或者恢复到某个事务提交之前这就要用到PITRPoint-In-Time Recovery。恢复步骤大体如下将备份后产生的所有WAL归档文件按时间顺序放到一个可访问的目录比如/archive_wal。编辑postgresql.conf配置恢复参数restore_command cp /archive_wal/%f %p recovery_target_time 2025-01-15 14:30:0008 # 或者按事务ID恢复recovery_target_xid 100001 # 或者恢复到时间线末recovery_target immediate启动实例它会进入恢复模式自动重放WAL到目标时间点。确认恢复结果无误后执行SELECT pg_wal_replay_resume(); SELECT pg_is_in_recovery();当pg_is_in_recovery返回false说明恢复完成实例已进入正常读写状态。PITR有个关键前提备份之后的所有WAL必须完整。如果你的WAL归档断档了恢复就只能到断档点之前。所以生产环境务必把archive_mode打开并且定期检查归档目录的连续性。4.3 校验备份有效性的方法恢复完成能正常启动只是第一步还要做业务层校验关键表行数对比抽查几张核心业务表主备恢复端数据量应该一致近期事务是否存在特别是备份点之后、恢复目标点之前提交的事务应当都能查到序列当前值是否合理很多恢复后才发现自增id冲突本质是序列的last_value落后于实际数据我自己习惯做一套固定的恢复后验收清单检查项方法预期实例启动pg_ctl statusrunning只读状态SELECT pg_is_in_recovery()truePITR中WAL回放进度SELECT pg_last_wal_replay_lsn()持续推进数据一致性对账表行数、序列值与主库一致应用连通性用真实连接串跑一条读SQL正常返回备份不是生成出来的是恢复成功的才叫备份。这句话值得每个数据库负责人反复记。5. 实测中容易踩的坑从权限到网络再到磁盘5.1 权限坑还是最多的pg_basebackup对权限的要求比想象中严格。它需要备份用户的 replication 权限目标目录的写权限目录属主一般要是postgres系统用户如果有表空间对应表空间路径的写权限最典型的报错是pg_basebackup: error: could not initiate base backup: ERROR: permission denied for function pg_start_backup这个就代表你用了没有replication权限的账号。有些环境用超级用户postgres执行上文提到过普通超级用户不行不够准确实际上超级用户具备replication权限直接用postgres账号也能跑通但如果公司安全规范比较严一般还是单独建replica_user把权限最小化。另外别忘了pg_hba.conf的replication条目很多连接报错都出在这。改配置后务必reload否则当时就生效不了。5.2 网络与超时问题大库备份时网络中断或连接超时是最痛苦的。两个实用建议主库的wal_sender_timeout别设太短默认60秒在跨机房高延迟链路上可能引起频繁断开建议调到300秒以上。客户端备份工具的pg_basebackup本身有重试机制吗答案是部分但如果数据已经传了一半断掉只能重来。所以大库备份建议用screen或nohup挂后台或者直接用tmux防止终端关掉导致备份进程被杀。跨机房备份时-X stream会实时消耗主库与备份机之间的带宽。如果带宽有限可以改用-X fetch配合归档目录让WAL通过归档进程慢慢补齐但前提是archive_mode和archive_command配置正常。5.3 磁盘与目录坑目标目录不为空会直接报错pg_basebackup: error: directory /data/pgdata exists but is not empty此时别去清空目标目录里的文件先把目录删了重建确保权限正确。如果目标目录是软链接或挂载点也容易出现异常建议用一个真实目录。另一个容易忽略的是空间预估。pg_basebackup备份一个200GB的库目标目录至少要预留200GB考虑到备份期间的WAL、临时文件、以及tar包的多份拷贝实际建议按源库的1.5到2倍空间来规划。否则备份到一半磁盘写满只能删了重来。5.4 备份过程中的锁与负载备份过程虽然允许业务继续读写但开始和结束瞬间都会触发检查点-c fast会立即触发一个快速检查点。大实例的快速检查点会带来一定的IO尖峰可能导致主库短时间出现慢查询。经验是业务高峰期别做全量备份一般安排在凌晨低峰窗口并且用-c spread平滑检查点把IO压力摊开。5.5 复制槽位与WAL保留机制如果你不创建复制槽位备份期间主库可能已经提前把某个WAL段清理掉导致备份恢复时缺日志。虽然-X stream模式下WAL是实时跟随的但实时是有窗口的。稳妥起见给备份创建一个临时槽位pg_basebackup -h 192.168.1.10 -U replica_user \ -D /backup/pgdata_backup \ -X stream -C -S backup_slot_20250115 -P -v备份完成后槽位会被自动保留在主库上需要手动清理SELECT pg_drop_replication_slot(backup_slot_20250115);别创建完就不管了长期不用的复制槽位会让主库WAL持续累积最终拖垮磁盘。6. 备份策略选型pg_basebackup与专业备份工具日常聊数据库备份很多人会问既然有pg_basebackup那pg_probackup、pgBackRest这类专业工具还有必要用吗我的观点是分场景。pg_basebackup是官方自带工具零依赖、和PostgreSQL版本天然匹配、部署最方便。对于中小环境、单实例、偶尔搭建从库、手动恢复演练的场景它就是最可靠的选择。但它也有明显的短板不支持增量备份、压缩能力有限、没有统一的备份管理界面、跨版本升级后老备份兼容性需要自己把控。专业备份工具的核心优势在于增量备份和备份生命周期管理。比如pgBackRest支持全量增量差异备份三层组合配合合理的保留策略可以让每天的备份量和恢复RPO都更友好。pg_probackup则提供了更细粒度的备份目录管理和校验功能。能力pg_basebackuppgBackRestpg_probackup全量备份支持支持支持增量备份不支持支持支持压缩有限tar格式支持多种算法支持加密不支持支持支持备份保留策略需要脚本自管内置内置恢复编排手动内置内置上手成本低中中选型建议比较直接库不大几百GB以内、实例数量少、没有专职DBA用pg_basebackup就够了写个cron脚本每天全量加WAL归档做增量遇到故障能恢复。库大TB级以上、实例多、需要稳定增量备份链上pgBackRest或pg_probackup把备份任务纳入统一管理。对恢复时间目标RTO有严格要求的场景光有备份还不够要配套流复制从库做主从切换备份只是兜底。最后分享一个我自己的习惯无论用哪种工具每个季度至少做一次完整的恢复演练从备份文件到启动实例再到业务对账全程计时记录。备份这件事平时看不见价值但真到了故障发生那一刻能不能快速恢复靠的就是平时那一次次多此一举的演练。