懂得正确地提出问题,也是一项重要的本领
前言
这几天,一位读者咨询了我这样一个问题:
如果有自定义的表空间,那么如何用 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 中:
voidcheck_and_dump_old_cluster(bool live_check){/* -- OLD -- */if (!live_check)start_postmaster(&old_cluster, true);/** Extract a list of databases, tables, and logical replication slots from* the old cluster.*/get_db_rel_and_slot_infos(&old_cluster, live_check);init_tablespaces();get_loadable_libraries();...voidinit_tablespaces(void){get_tablespace_paths();set_tablespace_directory_suffix(&old_cluster);set_tablespace_directory_suffix(&new_cluster);if (os_info.num_old_tablespaces > 0 &&strcmp(old_cluster.tablespace_suffix, new_cluster.tablespace_suffix) == 0)pg_fatal("Cannot upgrade to/from the same system catalog version when\n""using tablespaces.");}staticvoidset_tablespace_directory_suffix(ClusterInfo *cluster){/* This cluster has a version-specific subdirectory *//* The leading slash is needed to start a new directory. */cluster->tablespace_suffix = psprintf("/PG_%s_%d",cluster->major_version_str,cluster->controldata.cat_ver);}
代码逻辑很简单,就是比较新老集群的表空间的后缀名字
•cluster->major_version_str:PostgreSQL 的主版本号(比如 "14" 或 "15" 等)•cluster->controldata.cat_ver:PostgreSQL 集群的 Catalog version number
到这里,不得不提一下表空间的命名方式了:PG + 主版本号 + CATALOG_VERSION_NO:
/** Name of major-version-specific tablespace subdirectories*/#define TABLESPACE_VERSION_DIRECTORY "PG_" PG_MAJORVERSION "_" \CppAsString2(CATALOG_VERSION_NO)
CATALOG_VERSION_NO 可以使用 SQL 或者 pg_controldata 进行查询,主要目的是防止针对格式不兼容的数据目录进行启动:
postgres=# select*from pg_control_system();pg_control_version | catalog_version_no | system_identifier | pg_control_last_modified--------------------+--------------------+---------------------+--------------------------1300|202404021|7456358899425219394|2025-02-2410:16:58+08(1row)
所以按照这个命名方式,假如我新建一个表空间,那么命名将是 PG_17_202404021:
postgres=# create tablespace myspace location '/home/postgres/myspace';CREATE TABLESPACE[postgres@mypg~]$ ls -l 17data/pg_tblspc/16702/total 4drwx------ 2 postgres postgres 4096 Feb 27 16:57 PG_17_202404021
那么回到问题中来,如果是不同大版本,主版本号就不同了,不应该报错,为何会报错呢?就在我百思不得其解之时,我又问了一下这位读者更多信息:
我这边是测试 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[1]
References
[1]: https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md