1. 升级前夜:为什么选择pg_upgrade,以及你必须知道的几件事
朋友们,最近PostgreSQL 17.0正式发布了,相信不少守着16.3版本的朋友已经心痒痒了。新版本带来的性能提升和新特性确实诱人,但一想到要升级数据库,尤其是里面躺着几十上百GB的业务数据,是不是瞬间就冷静下来了?别慌,今天我就来手把手带你走一遍从PostgreSQL 16.3升级到17.0的全过程,用的就是官方推荐的pg_upgrade工具。我自己在测试环境和生产环境都实操过好几轮,踩过的坑、总结的经验,都会在这篇文章里毫无保留地分享给你。
首先,我们得搞清楚pg_upgrade到底是个啥。你可以把它想象成一个数据库的“搬家神器”,但它的聪明之处在于,它不是把数据一条条重新插入(那太慢了),而是直接复用旧版本的数据文件,只重建系统表。这就好比你要升级一个图书馆的管理系统,pg_upgrade的做法是:保留所有图书(用户数据)原来的位置和编号不变,只重新制作一份新的图书目录卡(系统表)。这种方式最大的好处就是快,尤其是数据量大的时候,优势非常明显。
那么,什么情况下你应该毫不犹豫地选择pg_upgrade呢?我总结了几点:第一,你的数据库体积很大,用逻辑导出导入(pg_dump/pg_restore)耗时太长,停机窗口不允许;第二,你对升级速度有要求,希望业务中断时间尽可能短;第三,你希望升级过程尽可能简单,一步到位。当然,天下没有免费的午餐,pg_upgrade这种“硬升级”方式对环境的准备要求也更严格,这也是我们后面要重点讲的部分。
在真正动手之前,有一个核心原则我必须反复强调:备份!备份!备份! 无论教程看起来多么万无一失,在生产环境操作前,一定要有完整的、可恢复的备份。我自己的习惯是,除了用pg_dumpall做一次逻辑全备之外,还会在文件系统层面给整个PGDATA目录打个快照(如果存储支持的话)。这样万一升级过程出现任何不可预知的问题,我们都有退路,心里不慌。记住,对于DBA来说,数据安全永远是第一位的,任何操作都不能以牺牲数据安全为代价。
2. 战前准备:搭建舞台,扫清升级路上的“地雷”
好了,决心已下,备份也已就位,接下来我们就要为升级搭建一个安全的舞台。这一步看似琐碎,但却是决定升级成败的关键。很多升级失败案例,回头一看,问题都出在准备阶段没做足功课。
2.1 兼容性检查:让pg_upgrade先帮你“预演”一遍
pg_upgrade提供了一个超级好用的-c(check)参数。这个参数的作用就是进行一次“演习”,它会全面检查新旧两个集群是否兼容,但不会真正修改任何数据。我强烈建议你,在任何一次正式升级前,都先完整跑一遍检查。命令大概长这样:
/usr/local/pg17/bin/pg_upgrade \
-b /usr/local/pg16/bin \
-B /usr/local/pg17/bin \
-d /data/pg16 \
-D /data/pg17 \
-p 5432 \
-P 5433 \
-c
这里解释几个关键参数:-b和-B分别指定旧版本和新版本的可执行文件路径;-d和-D分别指定旧集群和新集群的数据目录;-p和-P指定端口。注意,运行这个检查时,新旧两个PostgreSQL实例都需要处于停止状态。我刚开始就犯过这个错误,新集群的postmaster进程没关,检查直接报错退出了。
跑完检查后,如果一切顺利,你会看到最后一行写着*Clusters are compatible*,那感觉就像考试通过了似的。但更常见的情况是,它会给你抛出几个错误或警告。别怕,这正是检查的意义所在。最常见的错误之一就是“缺少共享库”,比如原文中遇到的:
Checking for presence of required libraries fatal
could not load library "$libdir/pg_stat_statements"
这意思是说,你的旧数据库里使用了pg_stat_statements这个扩展(插件),但新安装的PostgreSQL 17里还没有编译安装这个扩展。pg_upgrade要求新旧集群的扩展必须同时存在。解决办法就是,去新版本的源码目录的contrib文件夹下,找到对应的扩展,重新编译安装。比如:
cd /soft/postgresql-17.0/contrib/pg_stat_statements
make && make install


890

被折叠的 条评论
为什么被折叠?



