前言
这几天,一位读者咨询了我这样一个问题:
如果有自定义的表空间,那么如何用 pg_upgrade 进行大版本升级呢,我自己测试了,发现会报错,那如果 pg_upgrade 不行的话,那还有什么工具升级大版本呢。还是说只能够通过数据的逻辑导出导入的方式进行升级
愣是一下子没有反应过来,印象中 pg_upgrade 会妥善处理好表空间。当分析清楚问题根因之后,再次感叹,懂得正确地提出问题,也是一项重要的本领。
分析
首先,大版本升级并不仅限于 pg_upgrade 和逻辑导入导出,还有逻辑复制,三者各有优劣,此处表过不提。
回到 pg_upgrade,印象中是可以正确处理表空间的,包括在官方文档中也并没有提及有相关限制。于是要了一个详细的错误截图:
可以看到,提示 “Cannot upgrade to/from the same system catalog version when using tablespaces”,代码很好找,位于 pg_upgrade.c 中:
1 | void |
代码逻辑很简单,就是比较新老集群的表空间的后缀名字
cluster->major_version_str
:PostgreSQL 的主版本号(比如 “14” 或 “15” 等)cluster->controldata.cat_ver
:PostgreSQL 集群的 Catalog version number
到这里,不得不提一下表空间的命名方式了:PG + 主版本号 + CATALOG_VERSION_NO:
1 | /* |
CATALOG_VERSION_NO 可以使用 SQL 或者 pg_controldata 进行查询,主要目的是防止针对格式不兼容的数据目录进行启动:
1 | postgres=# select * from pg_control_system(); |
所以按照这个命名方式,假如我新建一个表空间,那么命名将是 PG_17_202404021:
1 | postgres=# create tablespace myspace location '/home/postgres/myspace'; |
那么回到问题中来,如果是不同大版本,主版本号就不同了,不应该报错,为何会报错呢?就在我百思不得其解之时,我又问了一下这位读者更多信息:
我这边是测试 14.7 升级到 14.17
我是看到这个 pg_upgrade 小版本升级报错了,就以为大版本也会有问题
🙃🙃🙃好吧,原来是一场乌龙,只是因为上下文不够清晰,小版本只需替换二进制,然后重启就行了。
小结
懂得正确地提出问题,也是一项重要的本领。作者”人神共奋的李刚”就说:
职场中,70% 的时间花在各种沟通 (听说读写) 上,真正完成任务的时间不足 30%,造成群体工作绩效低的第一大原因就是”沟通不良”,而沟通不良的第一大杀手就是不会问问题。
精确地描述问题并言之有物是十分重要的,以《提问的智慧》为例:
- 仔细、清楚地描述你的问题或 Bug 的症状。
- 描述问题发生的环境(机器配置、操作系统、应用程序、以及相关的信息),提供经销商的发行版和版本号 (如:Fedora Core 4、Slackware 9.1等)。
- 描述在提问前你是怎样去研究和理解这个问题的。
- 描述在提问前为确定问题而采取的诊断步骤。
- 描述最近做过什么可能相关的硬件或软件变更。
- 尽可能地提供一个可以重现这个问题的可控环境的方法。
这个案例,如果事先说明是小版本升级,那么我就不用任何思考即可作出回答,也不需要花费时间去看代码,毕竟大家的时间都非常宝贵,回答问题也不是义务。最后,推荐各位都阅读一下《提问的智慧》
参考
https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md