Aurora PG 14 快 EOL 了,我用蓝绿部署 52 秒切到了 PG 16,聊聊全过程
前两天跟同事吃饭,聊到数据库升级这个话题。他说他们还在 PG 13 上跑,问我升级到底有多麻烦。我说看你用什么方案------如果是亚马逊云科技的 Aurora,蓝绿部署这条路走一遍,你会发现比想象中简单太多。
但"简单"不等于"不需要准备"。我上周刚把生产环境三个集群从 14.9 升到 16.4,停机 52 秒完事。代价是前面花了大概一周时间做准备工作。这篇把整个过程拆开来讲,你看完可以直接照着做。
为什么不能再拖了
PG 14 的社区 EOL 是 2026 年 11 月。你不自己升,亚马逊云科技会在 EOL 后强制升级。强制升级的意思是------在维护窗口自动执行,时间不是你选的,方式不是你定的。
听起来挺省事?但如果恰好赶上你的业务高峰期呢?如果升级后出了优化器回退你都不知道什么时候开始的呢?自己控制节奏总比被动好。
先说结论:我选了蓝绿部署
三种方案我都评估过:
| 方案 | 我的体验 |
|---|---|
| 蓝绿部署 | 停机 52 秒,可回滚,推荐 |
| 原地升级 | 简单粗暴但不能回滚,心里没底 |
| Clone + DMS | TB 级才需要,我们 80GB 用不上 |
蓝绿部署的本质:系统在后台创建一个 PG 16 的新集群(绿环境),从旧集群持续同步数据。你验证没问题后执行切换,DNS 端点自动切过去。整个过程中旧集群完全不受影响,业务熇常跑。
原地升级虽然操作简单,但它是单程票------一旦开始就回不了头。出了问题只能恢复快照,那个恢复时间就不是分钟级别了。
升级前的保命操作:性能基线
折腾了三天才学到的教训------不建基线就升级,等于蒙着眼过马路。
开启 pg_stat_statements
sql
-- 检查是否已加载
SHOW shared_preload_libraries;
-- 如果没有,需要在 AWS 控制台的参数组中添加(注意:要重启实例)
-- 创建扩展
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
-- 导出 Top 20 SQL
SELECT
substring(query, 1, 80) AS short_query,
calls,
round(total_exec_time::numeric, 2) AS total_ms,
round(mean_exec_time::numeric, 2) AS avg_ms,
rows
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 20;
导出 CSV 存档
bash
psql -h your-aurora-cluster.xxx.rds.amazonaws.com -U postgres -d mydb \
-c "SELECT query, calls, total_exec_time, mean_exec_time, rows \
FROM pg_stat_statements ORDER BY total_exec_time DESC LIMIT 50" \
--csv > baseline_before_upgrade.csv
这个 CSV 就是你的安全网。升级前后的对比全靠它。建议连同集群当前负载状态一起记录下来。
保存执行计划
挑 5-10 条核心业务 SQL,跑 EXPLAIN (ANALYZE, BUFFERS) 保存。这些是升级后对比优化器行为的关键材料。
sql
EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON)
SELECT o.id, o.status, c.name
FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE o.created_at > now() - interval '7 days'
AND o.status = 'pending';
我们升到 16 后有条 SQL 的执行计划从 Hash Join 变成了 Merge Join。因为有基线,5 分钟就确认了这是正向优化而不是回退。要是没有基线数据,这种变化可能一周后才被发现,那时候再排查就头疼了。
蓝绿部署实操
第一步:建参数组(别跳过!)
这步我差点翻车。PG 16 跟 PG 14 的参数组不完全兼容,有些参数改了名字或者被直接移除了。我第一次创建蓝绿部署的时候才发现没有 PG 16 的参数组,临时建的配置不对,又重来了一遍。白白浪费了两个小时。
血泪教训:参数组一定要提前建好,并在测试环境验证通过。
第二步:创建蓝绿部署
bash
aws rds create-blue-green-deployment \
--blue-green-deployment-name "pg14-to-pg16" \
--source "arn:aws:rds:us-east-1:123456789012:cluster:my-cluster" \
--target-engine-version "16.4" \
--target-db-parameter-group-name "aurora-pg16-params" \
--target-db-cluster-parameter-group-name "aurora-pg16-cluster-params"
等绿环境就绪,我们 80GB 的库花了 18 分钟:
bash
aws rds describe-blue-green-deployments \
--blue-green-deployment-identifier "bg-xxxxx" \
--query 'BlueGreenDeployments[0].Status'
第三步:在绿环境上跑验证
连到绿环境端点,把之前保存的核心 SQL 一条条跑一遍。重点看执行计划有没有变化、性能有没有回退。
sql
-- 先 ANALYZE 更新统计信息
ANALYZE VERBOSE;
-- 逐一对比核心 SQL 的执行计划
EXPLAIN (ANALYZE, BUFFERS)
SELECT o.id, o.status, c.name
FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE o.created_at > now() - interval '7 days'
AND o.status = 'pending';
第四步:切!
确认没问题后,选了周三凌晨 3 点(业务低谷期)执行切换:
bash
aws rds switchover-blue-green-deployment \
--blue-green-deployment-identifier "bg-xxxxx" \
--switchover-timeout 300
52 秒完事。DNS 端点不变,应用不用改连接字符串。这段时间内写请求会失败,所以一定要选低峰期。
踩坑实录
坑 1:Extension 没更新
切完发现 pg_stat_statements 查询报错------Extension 版本还是旧的。这个坑出现频率特别高,文档里又不太显眼:
sql
ALTER EXTENSION pg_stat_statements UPDATE;
ALTER EXTENSION postgis UPDATE;
ALTER EXTENSION pg_trgm UPDATE;
记住:大版本升级后,Extension 不会自动更新,需要手动执行。
坑 2:连接池短暂断开
切换改了底层 IP,PgBouncer 里的旧连接全部失效。好在 PgBouncer 有自动重连机制,大概 30 秒后恢复正常。但这 30 秒里有少量请求报了连接错误。
改进方案:切换前把连接池的 idle timeout 调到 5 秒,让旧连接提前释放,减少切换时的错误量。
坑 3:个别查询变慢
大部分查询性能持平甚至更好,但有一条聚合查询慢了 20%。对比执行计划发现 PG 16 选了不同的 Join 策略。用 SET enable_hashjoin = off 临时验证确认后,通过 pg_hint_plan 固定了执行计划。
升级后验证清单
bash
#!/bin/bash
echo "=== 版本确认 ==="
psql -c "SELECT version();"
echo "=== Extension 状态 ==="
psql -c "SELECT extname, extversion FROM pg_extension;"
echo "=== ANALYZE ==="
psql -c "ANALYZE VERBOSE;"
echo "=== Top SQL 对比 ==="
psql -c "SELECT substring(query,1,60), calls, round(mean_exec_time::numeric,2) as avg_ms
FROM pg_stat_statements ORDER BY total_exec_time DESC LIMIT 10;"
echo "=== 连接数 ==="
psql -c "SELECT count(*) FROM pg_stat_activity WHERE state = 'active';"
我的升级清单总结
- 建基线 --- 没有基线数据就别动手
- 建参数组 --- 提前建、提前在测试环境验证
- 蓝绿部署 --- 创建绿环境 → 验证 → 低峰期切换
- Extension UPDATE --- 切完第一件事
- ANALYZE --- 切完第二件事
- 持续观察 --- 1-2 周内密切关注 pg_stat_statements 数据
原地升级和 Clone + DMS 也说两句
原地升级就一条命令:
bash
aws rds modify-db-cluster \
--db-cluster-identifier my-cluster \
--engine-version "16.4" --apply-immediately
优点是简单。缺点是停机 10-30 分钟,而且不能回滚。一定要在升级前手动打个快照保底:
bash
aws rds create-db-cluster-snapshot \
--db-cluster-identifier my-cluster \
--db-cluster-snapshot-identifier "pre-upgrade-snapshot"
Clone + DMS 就不展开了------Clone 现有集群、在 Clone 上原地升级、用 DMS 做 CDC 持续复制、最后切流量。适合 TB 级大库,但 CDC 配置、序列同步这些细节很折腾。80GB 以下的库,蓝绿部署足够了。
PG 14 的倒计时已经开始了。找个非生产环境先练一遍------我第一次在 staging 上做的时候花了 3 小时,第二次生产环境全程 40 分钟就搞定了。熟练度真的很重要。