29.6 多集群迁移环境
Pigsty 能把两个 PostgreSQL 集群、服务发现、连接池、监控和配置组织在同一个管理面里, 但迁移的数据面仍跨越两个独立系统。最危险的自动化错误,往往不是 SQL 写错,而是把 命令发到了正确环境中的错误 cluster、database 或 service。
本节把端点身份、凭据、观测和退出窗口做成多集群迁移的硬边界。
29.6.1 源、目标、验证端点与隔离凭据
给每类动作一个明确端点
| 端点 | 连接对象 | 允许动作 | 不应承担 |
|---|---|---|---|
| source migration | 源 primary/direct-write service | 建 publication/slot、读快照、写 marker | 普通应用写 |
| source runtime | 源业务 service | 迁移前业务读写,冻结后负向 canary | 管理 slot |
| target migration | 目标 primary/direct-write service | 建 schema/subscription、装载、sequence | 源端管理 |
| target runtime | 目标业务 service | 影子读、切流后业务读写 | 超级用户迁移 DDL |
| verification | 两端只读连接 | manifest、目录、业务不变量 | 修复或路由变更 |
| monitoring | exporter/API/dashboard | 采集两端与代理指标 | 作为业务正确性的唯一证据 |
源 logical replication 连接必须到能够创建 slot、持续发送 WAL 的 primary。目标 subscription 在目标 database 中创建,apply 写目标表。不要把“read service”名称当作 复制端点,也不要把 HA service 的自动切换能力误认为 slot 已具备 failover 语义。
每次 run 先打印并保存非秘密身份:
SELECT current_database(),
current_user,
inet_server_addr(),
inet_server_port(),
current_setting('server_version'),
pg_is_in_recovery();
SELECT system_identifier
FROM pg_control_system();并断言 source 与 target system_identifier 不同。database 名称相同不等于同一个
数据源,IP 不同也不保证不是同一 cluster 的两个实例。
凭据按职责和环境隔离
至少拆分:
source runtime
target runtime
replication/login
migration DDL
verification read-only
monitoringreplication 角色需要源端 LOGIN REPLICATION,initial copy 还需要 published table
的 SELECT;它不需要目标端 DDL。目标 runtime 不应能回写源。验证角色不应因为要比较
数据而获得修复权限。
连接合同还包括:
- TLS mode、CA 与 hostname verification;
- 精确 HBA source CIDR 和 role classification;
CONNECT、schemaUSAGE、table privilege;- secret manager 引用、有效期和轮换 owner;
- conninfo 禁止出现在公开证据、进程参数或 shell trace;
- 迁移完成后的 revoke/rotate 清单。
本章第一次候选实验在插入 fixture 之前就被 Pigsty HBA 拒绝:临时登录角色没有加入
HBA 所使用的平台分类角色。实验没有放宽成全网 trust,而是把 runtime 与 replication
账号分别加入 dbrole_readwrite / dbrole_readonly,并使用
INHERIT FALSE, SET FALSE,只满足成员分类,不继承平台对象权限。失败候选随后按 marker
精确清理,确认两端 database、role、slot 与 subscription 都不存在。
这条失败很有价值:HBA 的“能否建立连接”和 SQL grant 的“连上后能做什么”是两道 独立门。
Pigsty 迁移上下文是编排模板,不是控制平面替身
Pigsty 的 pgsql-migration.yml 可以围绕 source/target inventory 生成并组织:
check-user / check-db / check-hba / check-repl / check-misc
copy-schema
create-pub / create-sub
copy-progress / copy-diff
copy-seq以及需要 operator 落实的 source disable 和 re-routing 步骤。使用时应:
- 固定 Pigsty/模板版本;
- 审阅生成的变量、端点和 SQL;
- 把生成物与迁移 ticket 绑定;
- 在 disposable database 完整演练;
- 由实际应用/网络 owner 实施写围栏与切流;
- 用 PostgreSQL catalog 和应用身份反向复核。
本章正式实验在本地开发环境以 pg-test 为源、pg-meta 为目标,各自创建一次性
database 和角色。这只是为了在有限实验环境里证明真正的双 cluster 边界。生产中不应
因为教程这样做,就把承担 Pigsty 管理面的 pg-meta 当成默认业务迁移目标。
29.6.2 观察槽、WAL、延迟与切换流量
先用原生视图定义信号
源端:
SELECT slot_name,
database,
active,
active_pid,
restart_lsn,
confirmed_flush_lsn,
pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) AS retained_bytes,
wal_status,
safe_wal_size,
inactive_since,
invalidation_reason,
failover,
synced
FROM pg_replication_slots
WHERE slot_name = 'pg36_shop_slot';目标端:
SELECT subname,
worker_type,
pid,
received_lsn,
latest_end_lsn,
last_msg_send_time,
last_msg_receipt_time,
latest_end_time
FROM pg_stat_subscription
WHERE subname = 'pg36_shop_sub';
SELECT *
FROM pg_stat_subscription_stats
WHERE subname = 'pg36_shop_sub';再加上 pg_subscription_rel table state、PostgreSQL log 和业务 marker。不同版本的
视图列会变化,自动化应先断言 server major,而不是对未知列 SELECT * 后按位置解析。
关键关系是:
consumer stopped
-> confirmed position stops
-> restart_lsn cannot advance
-> retained WAL grows
-> disk pressure or slot invalidation正式实验禁用 subscription 后确认 slot inactive,生成 3,000 条变化:
retained WAL: 227,008 -> 2,867,128 bytes
confirmed_flush_lsn: unchanged during stall重新启用后才追平。这个小规模实验不能给生产容量一个固定阈值,却证明“subscriber 不工作”会转化为 publisher 的磁盘风险。
max_slot_wal_keep_size 可以限制 checkpoint 时 slot 允许保留的 WAL;超过后 slot
可能失去继续消费所需的 WAL,而不是自动帮 consumer 修好。PostgreSQL 18 的
idle_replication_slot_timeout 可以在 checkpoint 时使长期闲置 slot 失效,synced
slot 有例外。二者都是保险丝,不能代替 owner、告警、rebootstrap 方案和容量预算。
Pigsty 视图负责聚合,catalog 负责定案
Pigsty 的 PGSQL、Replication、Persist、Service 与 Proxy 等 dashboard 可以统一观察:
source WAL and replication
target TPS/latency/locks
disk and checkpoint
service health and connection distribution
pool/proxy sessionsdashboard 适合关联趋势和告警;切流门禁仍应把关键 catalog query、时间范围和截图/导出 写入证据包。监控抓取间隔可能错过瞬时状态,面板也不会知道 marker 是否已被应用查询 读到。
logical slot failover 需要一整组前提
PostgreSQL 18 支持 failover logical slot,但不能只设置 failover = true 就宣称源端
primary 可无缝切换。完整设计还涉及:
- primary 上 slot 标记为 failover;
- standby 启用
sync_replication_slots; - standby 配置
primary_slot_name和可用的 physical replication slot; primary_conninfo包含可连接到正确 database 的配置;- physical standby 向上游提供所需 feedback;
- 对需要的同步边界使用
synchronized_standby_slots; - 切换前确认目标 standby 上对应 slot 已
synced且位置安全; - connector/subscriber 重新连接后的 endpoint 与 timeline 测试。
这些参数影响可用性、WAL 保留和复制反馈,必须在与生产同构的故障切换演练中验证。 未做这套设计时,源 primary failover 可能要求重新 bootstrap;迁移窗口要把它列为明确 故障分支。
路由观测与数据复制是两条链
publication/subscription 不知道业务连接走 DNS、HAProxy、PgBouncer 还是配置中心。 切流证据至少包括:
route control plane generation
resolved endpoint before/after
new connection system identifier
old/new pool active sessions
source runtime DML denial
target runtime canary
rollback endpoint and drain status监控图中的目标 TPS 上升只是旁证。最强证据是使用真实 runtime 凭据建立一个新连接, 验证目标系统身份并完成可回读 canary。
29.6.3 保留源环境直到退出观察窗口
保留不是继续双主写入
切流后的源环境应进入受保护状态:
runtime writes fenced
normal reads limited to verification
backup and required WAL retained
schema changes frozen
credentials and network path controlled
monitoring remains active
no scheduled job silently resumes writes这样它既能支持调查和条件回退,又不会继续产生与目标分叉的新事实。若业务需要 reverse replication,应把它作为独立的数据合同:方向、冲突、sequence、DDL、RPO 和停止点都要 明确,不能把两个方向各建一个 subscription 就叫 active-active。
退出窗口用条件,不只用日期
观察窗口可以有最短时长,但退出还应同时满足:
- 所有应用、worker、ETL、BI 和管理入口已迁到目标;
- 旧 service/pool 不再产生业务连接;
- 目标 SLO 经历了至少一个代表性高峰和关键批任务;
- manifest、分桶和业务不变量连续通过;
- 目标独占写边界与备份恢复已验证;
- 告警、值班、容量和灾备 runbook 已移交;
- 迁移临时 slot/subscription/reject 已有保留或清理决策;
- source 回退 SLA 已到期,并有 owner 签收;
- 资产、CMDB、DNS、secret 与文档已更新。
如果月末关账是系统最关键路径,只观察一个低峰小时即使所有图都绿色,也没有覆盖真实 业务周期。
清理按依赖方向进行
正常 subscription 与远端 slot 仍关联且源端可达时,DROP SUBSCRIPTION 会尝试删除
远端 slot。若先断网络或删除源 database,目标端 drop 可能失败,源端还可能留下孤儿
slot。退出流程应:
- 记录 subscription、publication、slot、owner 和最终位置;
- 停止/确认 consumer 不再需要;
- 在两端都可达时正常删除 subscription;
- 在源端确认 main slot 与 table-sync slot 均不存在;
- 再删除 publication 和迁移临时角色/权限;
- 轮换生产凭据;
- 将 source decommission 作为独立、可审计且明确不可逆的变更。
不要使用“删除所有 inactive slot”“终止所有连接”或 DROP DATABASE ... WITH (FORCE)
作为通用收尾。正式实验的清理只匹配本 run 创建的 database、role、subscription 和
slot;没有终止无关 session,普通 database drop 即成功。
保留窗口结束后,旧源也不应无限期成为影子生产系统。无限保留会继续消耗备份、补丁、 监控与安全治理成本,还让团队误以为随时能回到一个早已过期的数据副本。退出签收就是 把“临时可回退”正式转化为“目标为唯一权威,恢复走新体系”。
上一节:异构同步的语义损失 · 返回本章目录 · 下一节:实战:迁移 pg36_shop ·
查看全书目录 · 查看索引中心