LabHub
学习 学习路径 课程

PostgreSQL 复制与提升

把复制立起来再做升主

在 LabHub 中继续学习

目标

同一个 Pod 内亲手建立主服务器与备用服务器,配置复制并完成晋级,最后观察 timeline 分叉。

为什么重要

“已经构建 HA”往往意味着从未真正做过故障切换。配置看似正确,晋级时却可能发现备用服务器没有跟上;或晋级成功但应用仍连接旧地址;也可能试图重新接入旧主库而破坏数据。

本实验会提前完整走一遍该流程。

环境

Pod 以 postgres 账号运行(实验 Pod 没有 capability,无法通过 su 切换用户),因此无需 susudo

psql                      주 서버(5432)에 바로 붙습니다
psql -h 127.0.0.1 -p 5433 대기 서버

**连接备用服务器时务必添加 -h 127.0.0.1。**本环境已把 Unix socket 目录移到 home 下,因为容器运行时用 tmpfs 覆盖 /run,默认路径会消失。

步骤

  1. 让主服务器支持复制
  2. 创建复制账号与 slot
  3. base backup → /var/lib/postgresql/standby
  4. 在 5433 启动备用服务器
  5. 验证复制 → /root/db/05-repl.txt
  6. 验证只读 → /root/db/06-readonly.txt
  7. 晋级
  8. 比较 timeline → /root/db/08-timeline.txt

参考

让主服务器支持复制

让主服务器支持复制

wal_levelmax_wal_sendersmax_replication_slotshot_standby 通过 alter system set 修改后重启。重启命令为 pg_ctl -D /var/lib/postgresql/data -w -t 40 restart -l /var/log/postgresql.logshow wal_level 必须为 replica。

复制账号与 slot

创建复制账号与 slot

使用 create role rep with replication login password 'rep' 创建账号,再用 select pg_create_physical_replication_slot('s1') 创建 slot。没有 slot 时,备用服务器短暂断开后,所需 WAL 可能已消失并导致复制损坏。

基础备份

基础备份 → /var/lib/postgresql/standby

PGPASSWORD=rep pg_basebackup -h 127.0.0.1 -U rep -D /var/lib/postgresql/standby -X stream -S s1 -R-R 会自动创建 standby.signal 与 primary_conninfo;这个文件标志着“你是备用服务器”。

让备用服务器使用 5433

在 5433 启动备用服务器

执行 echo "port=5433" >> /var/lib/postgresql/standby/postgresql.auto.conf,再运行 pg_ctl -D /var/lib/postgresql/standby -l /var/log/labhub/standby.log -w -t 40 start。用 psql -h 127.0.0.1 -p 5433 -tAc "select pg_is_in_recovery()" 确认结果为 t。

**务必添加 -h 127.0.0.1。**本环境移动了 Unix socket 目录,只改端口会找不到 socket 路径。

确认复制真实工作

验证复制 → /root/db/05-repl.txt

在主库执行 create table if not exists ha(id int)insert into ha values (42),两秒后确认备用库能看到相同行。把 select state, replay_lag from pg_stat_replication 的结果保存到 /root/db/05-repl.txt,state 必须是 streaming。

备用服务器为何拒绝写入

验证只读 → /root/db/06-readonly.txt

在备用服务器尝试 insert into ha values (1),把错误消息原样保存到 /root/db/06-readonly.txt。备用服务器无法自行生成 WAL,因此不能接受写入;这是结构限制,不是设置。

晋级

晋级

pg_ctl -D /var/lib/postgresql/standby promote 晋级。pg_is_in_recovery() 会变为 f,并可写入。晋级后尝试一次 insert

timeline 发生分叉

比较 timeline → /root/db/08-timeline.txt

晋级后新服务器会分叉到 timeline 2。比较两台服务器的 WAL 文件名,在 /root/db/08-timeline.txt 中写两行: psql -h 127.0.0.1 -p 5432 -tAc "select pg_walfile_name(pg_current_wal_lsn())" 与 5433 的结果。文件名前 8 位是 timeline(00000001 / 00000002)。

这正是旧主库不能直接重新接入的原因:两台服务器从同一点开始写出不同历史。必须使用 pg_rewind 回退到分叉点。