把复制立起来再做升主
目标
在同一个 Pod 内亲手建立主服务器与备用服务器,配置复制并完成晋级,最后观察 timeline 分叉。
为什么重要
“已经构建 HA”往往意味着从未真正做过故障切换。配置看似正确,晋级时却可能发现备用服务器没有跟上;或晋级成功但应用仍连接旧地址;也可能试图重新接入旧主库而破坏数据。
本实验会提前完整走一遍该流程。
环境
Pod 以 postgres 账号运行(实验 Pod 没有 capability,无法通过 su 切换用户),因此无需 su 或 sudo。
psql 주 서버(5432)에 바로 붙습니다
psql -h 127.0.0.1 -p 5433 대기 서버
**连接备用服务器时务必添加 -h 127.0.0.1。**本环境已把 Unix socket 目录移到 home 下,因为容器运行时用 tmpfs 覆盖 /run,默认路径会消失。
步骤
- 让主服务器支持复制
- 创建复制账号与 slot
- base backup →
/var/lib/postgresql/standby - 在 5433 启动备用服务器
- 验证复制 →
/root/db/05-repl.txt - 验证只读 →
/root/db/06-readonly.txt - 晋级
- 比较 timeline →
/root/db/08-timeline.txt
参考
- 出错时查看
/var/log/postgresql.log(主库)与/var/log/labhub/standby.log(备用库)。 pg_stat_replication只会在主服务器显示;在备用服务器为空是正常现象。
让主服务器支持复制
让主服务器支持复制
把 wal_level、max_wal_senders、max_replication_slots、hot_standby 通过 alter system set 修改后重启。重启命令为 pg_ctl -D /var/lib/postgresql/data -w -t 40 restart -l /var/log/postgresql.log。show 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 回退到分叉点。