Aurora Global:可执行的计划切换与回切
验证:未记录
- 适用版本
- 未记录
- 验证范围
- 尚未登记验证记录。
本篇将 EnterpriseRunbook 的写入隔离、数据水位和恢复落实为一个明确场景:已有 Aurora PostgreSQL Global Database,两区域、相同兼容引擎版本的计划切换。无计划区域失联可能损失数据,不能把本流程改成强制 failover 后宣称零丢失。
执行前填写 变更执行记录,约定停写预算、业务阈值与最晚恢复决策时间;任何检查结果未知都不推进切换。
1. 前置资产与验证#
两区域已配置私网集群、至少一个可承接写入的实例、备份、密钥授权和受控运维网络。使用 订单工程 的迁移与角色;A 应用只拿 a 角色,B 只拿 b 角色。迁移 owner 不下发业务。Global Database 的版本、区域限制按官方切换条件核对。
下载 static/examples/enterprise-orders/dr/,准备 AWS CLI、jq、psql、Python/psycopg。AWS 操作身份仅管理本次 Global Database 与两个集群,不授予业务角色 RDS 管理权限。
export AWS_REGION=REPLACE_CURRENT_PRIMARY_REGION
export EXPECTED_ACCOUNT_ID=REPLACE_ACCOUNT_ID
export GLOBAL_ID=REPLACE_GLOBAL_DATABASE_ID
export EXPECTED_SOURCE_ARN=REPLACE_SOURCE_CLUSTER_ARN
export TARGET_ARN=REPLACE_TARGET_CLUSTER_ARN
export CHANGE_ID=CHG-REPLACE
aws rds describe-global-clusters --global-cluster-identifier "$GLOBAL_ID"核对两个 ARN(Amazon Resource Name,资源名称)、唯一 writer、成员状态 available、复制延迟及实例容量。记录源/目标 endpoint、版本、KMS(密钥管理服务)与备份状态;任何异常先停止。
2. 冻结、排空与隔离#
- 暂停发布和入口新写入;旧 worker 排空,确认 outbox=0。
- 两边 API/worker 缩为 0,保存原副本数;对已在途事务等待提交或超时,不只关闭 DNS。
- 用当前主库只读身份执行下方对账命令。金额、行数保存,pending=0、inconsistent=0;摘要覆盖相同范围,文件写入成功不等于对账通过。
- owner 连接文件指向当前主库,运行
python3 dr/switch_writer.py --from-site a --to-site b --expected-epoch 1 --change-id "$CHANGE_ID"。控制记录进入 WAL(预写日志),a 身份从此被触发器拒绝。此时 B 仍无应用流量。
只要不能连接主库完成隔离与最终水位,就停止计划切换;转入独立事故决策,不能跳过隔离。
第 3 步的连接文件由受控凭据流程准备,权限 0600;PGSERVICEFILE 中的 source-readonly 指向当前主库,密码使用受保护的 passfile,TLS 使用 verify-full。READONLY_DSN_FILE 为同一只读连接的连接串文件,不在命令参数中展开密码。
umask 077
export PGSERVICEFILE='/run/secrets/dr-pg-service.conf'
export READONLY_DSN_FILE='/run/secrets/dr-source-readonly.dsn'
export OWNER_DSN_FILE='/run/secrets/dr-current-writer-owner.dsn'
PGSERVICE=source-readonly psql -X -w -v ON_ERROR_STOP=1 -f dr/reconcile.sql > evidence-before.txt
python3 dr/reconcile.py > evidence-before.json第 4 步仅在以上退出码均为 0、人工确认水位后执行。单写控制记录中的 site/epoch 必须实查;本文 a/1 → b/2 仅适用于初始状态,重跑不能复用旧 epoch。
3. 执行托管切换#
export CONFIRM_FROZEN_CHANGE="$CHANGE_ID"
bash dr/aurora-switchover.sh脚本检查账号、预期旧主、目标成员和操作状态,调用托管 switchover 后限时轮询。超时不代表失败或已回退;保持停写,检查进行中的 RDS 操作,不再次盲目提交。证据保存在 evidence/。
4. 数据及旧主验收#
- 新主连接用 TLS(传输层安全)验证,执行相同
reconcile.sql和reconcile.py(改为新主只读连接文件),在启用业务前与冻结水位逐项比较。计划切换要求相同;不一致停止。 - 新主
SELECT pg_is_in_recovery();应为 false。旧区域成员检查其托管只读状态,并以旧 a 角色尝试写订单:必须拒绝。若仍能写,保持入口关闭并处理数据库隔离。 - B 更新连接为目标写 endpoint,epoch=2,先启动 API/worker 并执行完整业务验收;失败只暂停 B,不直接打开 A。
- B 验收通过才切唯一入口,记录最终业务恢复时间。观测旧连接、重复请求、账本、积压与投影;客户端缓存不是数据隔离手段。
中止发生在哪一步#
| 当前阶段 | 恢复边界 |
|---|---|
| 尚未修改 writer_control,亦未提交托管切换 | 确认当前主仍为 A、B 隔离,恢复 A 原副本与入口 |
| writer_control 已改为 b/2,尚未提交切换 | 两侧继续停写;确认 AWS 无进行中的切换、唯一主仍为 A,再用 owner 按当前值将 b/2 改为 a/3;A 配置也改到 epoch=3 后才恢复 |
| 切换请求已提交、超时或返回未知状态 | 查询唯一 writer、成员状态和控制记录;保持停写,不重复执行脚本,也不在旧主直接翻转 epoch |
| B 已成为主库或已执行业务写入 | 先在 B 修复;确需回 A 时按第 5 节重新同步、冻结、隔离、对账与反向切换 |
每次改变写入控制都递增 epoch,不把它改回旧值。数据库角色切换成功不代表应用恢复;保留所有操作状态、业务门禁与旧身份拒写证据。
5. 回切#
B 已写入后,A 必须作为 Global Database 成员同步追平,不能从旧快照直接提供服务。重复冻结、排空和对账;在 B 主库将控制状态 b/2 切为 a/3,再反向运行同一脚本(交换 source/target ARN,AWS_REGION 改为当前主区域)。验收后才恢复 A 的入口。
RPO(恢复点目标)和 RTO(恢复时间目标)记录实际数据差异与业务恢复耗时。无计划 failover 的可接受损失、水位补偿、旧区域重新加入另按事故 runbook 执行,不复用“计划切换无损”的验收结论。
结束后恢复自动化、缩回备用容量,收回临时管理凭据;保留切换证据和恢复备份,不删除共享集群。