一、升级脚本编写
openGauss开发中涉及新增或修改系统函数、系统表等系统对象时需要新增或修改升级回滚脚本,以确保新增特性功能在升级场景中同样支持。
openGauss升级脚本位于src/include/catalog/upgrade_sql/目录下,一共有八类脚本:
- rollback_catalog_maindb
- rollback-post_catalog_maindb
- rollback_catalog_otherdb
- rollback-post_catalog_otherdb
- upgrade_catalog_maindb
- upgrade-post_catalog_maindb
- upgrade_catalog_otherdb
- upgrade-post_catalog_otherdb
其中rollback代表回滚脚本,upgrade代表升级脚本,回滚和升级脚本成对出现。maindb代表主数据库,即postgres,otherdb代表主数据库以外的其他数据库,maindb脚本和otherdb脚本也成对出现。-post脚本代表后置脚本,在升级后的数据库上执行,不带-post的脚本为前置脚本,前置脚本在升级前的数据库实例上执行,由于数据是同一份,前置脚本和后置脚本只需要写一种,升级后的数据库有更新的代码,通常推荐写后置脚本。
脚本后面带的数字是版本号,如果是修改升级脚本,且当时的版本还没有发布到外部,则可以直接修改当时的升级脚本而不用新增版本号。如果当时的版本已经发布或者是需要新增升级脚本,则需要在globals.cpp中对主版本号GRAND_VERSION_NUM加1,以此作为新增升级脚本的后缀。
历史版本的升级问题修改会复杂一点。
如果是6.0的升级脚本存在问题,6.0已发布,7.0合入了6.0的代码,7.0尚未发布,那么可以基于6.0的分支和版本增加版本号和新脚本,然后同步6.0的脚本到7.0的分支,因为7.0还未发布,所以可以不用改版本号,直接使用6.0的脚本。
如果7.0也已经发布,那么就需要基于各自的分支和版本号,增加版本号和新脚本。
元数据一致性很重要
元数据指的是各类系统对象,比如函数、表、视图、索引、操作符等等的属性,可以通过对应的系统表查询得到。升级脚本中的SQL语句创建的对象的元数据须跟直装时的元数据一致。例如新建函数,各项元数据需要跟builtin_funcs.ini中直装的系统函数的属性一致,比如oid、prostrict、provolatile、函数描述等属性(会发生变动的非系统对象oid等情况除外,通常>9999 的oid视为不确定的)。
元数据一致性指直接安装的A版本数据库,和从低版本B升级上来的A'数据库的系统对象元数据的一致性。
以系统函数为例,builtin_funcs.ini中,函数的属性由_0,_1,_2等配置项组成,每种配置项的具体含义可以从头文件fmgrtab.h中得知,可以与pg_proc的系统表对应https://docs.opengauss.org/zh/docs/latest/docs/DatabaseReference/PG_PROC.html。升级脚本则需要参考create funtion语句https://docs.opengauss.org/zh/docs/latest/docs/SQLReference/CREATE-FUNCTION.html,使得升级时创建的函数属性与直装时一致。
一个最常见的问题是描述,参考https://docs.opengauss.org/zh/docs/latest/docs/SQLReference/COMMENT.html,如果你的函数在builtin_funcs.init中的_33配置项不为NULL,那么需要在脚本中额外加上comment on语句创建对象描述,描述可以在系统表pg_description中查看,与对象oid相关联。描述在对象被删除后会自动删除,所以无需在回滚脚本中显式写明删除comment。
一个常见的函数元数据不一致的问题是proshippable,这个在builtin_funcs.ini中大量的历史系统函数都是初始化为NULL,但create function语句不能直接指定proshippable为NULL,只能指定为true或者false,默认为false,所以最好不要在builtin_funcs.ini中将_31配置项置为NULL。升级校验工具已经将该属性的NULL视为false进行校验。
oid GUC参数说明
撰写系统表变更脚本时,会使用到一个 GUC 参数 inplace_upgrade_next_system_object_oids,用于对新增的系统对象指定 oid 。
oid小于10000的系统对象的oid是固定的。10000~16383是系统预留给安装初始化过程中会即时新增的系统对象oid,不固定。从16384开始就是用户操作开始分配的oid。
inplace_upgrade_next_system_object_oids有几种使用方式,根据不同的对象类型,该 GUC 参数具有不同的字段数量,各字段间以逗号隔开。具体用法如下:
1、系统表 table
对象类型 | 字段 1 | 字段 2 | 字段 3 | 字段 4 | 字段 5 | 字段 6 | 字段 7 | |
---|---|---|---|---|---|---|---|---|
系统表 | 取值 | IUO_CATALOG | true / false | true / false | 0 - 9999 | 0 - 9999 | 0 - 9999 | 0 - 9999 |
涵义 | 表对象 | 是否共享表 | 是否创建物理表文件 | 表的 oid | 表行类型的 oid | TOAST 表的 oid 若无则为 0 | TOAST 表索引表的 oid; 若无则为 0 |
2、索引表
对象类型 | 字段 1 | 字段 2 | 字段 3 | 字段 4 | 字段 5 | 字段 6 | 字段 7 | |
---|---|---|---|---|---|---|---|---|
索引表 | 取值 | IUO_CATALOG | true / false | true / false | 0 | 0 | 0 | 0 - 9999 |
涵义 | 表对象 | 是否共享表 | 是否创建物理表文件 | 非主表 | 索引表无复合类型 | 索引表无 TOAST 表 | 索引表 oid |
3、函数 function
对象类型 | 字段 1 | 字段 2 | 字段 3 | 字段 4 | 字段 5 | 字段 6 | 字段 7 | |
---|---|---|---|---|---|---|---|---|
函数 | 取值 | IUO_PROC | 0 - 9999 | |||||
涵义 | 函数对象 | 函数 oid |
4、类型 type
对象类型 | 字段 1 | 字段 2 | 字段 3 | 字段 4 | 字段 5 | 字段 6 | 字段 7 | |
---|---|---|---|---|---|---|---|---|
类型 | 取值 | IUO_TYPE | 0 - 9999 | 0 - 9999 | b / p | |||
涵义 | 类型对象 | 类型 oid | 数组类型 oid;若无则为 0 | b:基础类型 p:伪类型 |
5、其它通用类型
对象类型 | 字段 1 | 字段 2 | 字段 3 | 字段 4 | 字段 5 | 字段 6 | 字段 7 | |
---|---|---|---|---|---|---|---|---|
其它通用对象 | 取值 | IUO_GENERAL | 0 - 9999 | |||||
涵义 | 一般对象 | 对象 oid |
升级元数据不一致问题的特殊情况
比如5.0.0升级到6.0.0与直接安装6.0.0元数据不一致,那么6.0.0版本就有两种状态,直接安装的元数据1版本和低版本升级上来的元数据2版本,假设我们修好的版本是6.0.1,从6.0.1回滚到6.0.0后,两种状态的元数据一致都满足是不可能的,只能回滚到一个正确的版本,所以对于修改历史升级元数据不一致问题可以只新增升级脚本而不新增回滚脚本,更早版本没有新增函数或其他系统对象的情况由之前的脚本的回滚脚本保证。更复杂的情况可能还需要具体情况具体分析。
二、升级验证
验证升级,需要先使用企业版安装的方式安装低版本数据库,企业版安装步骤可参考官方文档https://docs.opengauss.org/zh/docs/latest/docs/InstallationGuide/%E4%BC%81%E4%B8%9A%E7%89%88%E5%AE%89%E8%A3%85.html 。
开发的升级包需要自己打包,打包命令:
sh build.sh -m debug -3rd $BINARYLIBS -pkg
但server仓打包没有OM等工具,所以还需要去OM仓打包,或者使用社区官网上同版本已发布的OM包。一个简便的方法是下载官网的企业版完整包,解压后将自己打包好的开发包拷贝到解压目录,覆盖server包。
注意需要拷贝全部打包好的文件,升级回滚脚本在upgrade_sql压缩包中,sha256文件同样需要用于校验对应包的完整性。
升级步骤参考官网文档:https://docs.opengauss.org/zh/docs/latest/docs/DatabaseOMGuide/%E5%8D%87%E7%BA%A7%E6%B5%81%E7%A8%8B.html 。强烈建议安装和升级时均分离环境文件,避免环境变量混乱。分离环境预安装后需要source分离出来的环境文件。升级时使用与安装时相同的xml配置文件和envfile环境分离文件。
验证升级前,建议先在安装好的数据库中创建一个B兼容性数据库,以验证otherdb脚本和B兼容性。
注意升级时系统会将upgrade_mode设置为1 或2,写进postgresql.conf文件,在提交升级或回滚后才会设为0。upgrade_mode为非0时,创建b库时dolphin插件不会自动创建。
升级元数据校验
元数据的标准流程需要通过OM工具操作。
1. 通过企业版直接安装A版本数据库后,通过以下命令导出元数据地图,$PORT为安装的数据库端口号
gs_upgradechk export -p $PORT
2. 从低版本B升级到A'数据库后,通过以下命令进行校验,$MapPath为上一步导出的元数据地图路径
gs_upgradechk verify -p $PORT -v $MapPath
最后可获得元数据校验结果的md文件。这样会得到全部的元数据校验不一致的结果。
还有一种非常规方式可以快速的比对元数据差异。将升级脚本中创建的对象改名,在直装的数据库中执行创建出来,可直接通过查询系统表对比差异。
三、问题定位
升级或回滚时如遇sql脚本执行错误,根据报错的脚本是maindb还是otherdb,进入对应数据库,执行
alter system set upgrade_mode to 2;
set isinplaceupgrade to on;
可以绕过正常情况下无法操作系统对象的限制,再执行报错的sql语句进行复现、分析、debug等操作。也可以通过这种方式在开发环境数据库中测试升级sql。
四、常见问题:
数据库已安装,可能原因:
- 重装时未清理文件目录。
- 环境变量异常,查看$GAUSS_ENV,2表示已安装。设置export GAUSS_ENV=1,再重新执行gs_install。
从报错信息看是无法获取guc参数,原因通常是:
- 升级前需要先登录数据库修改密码,openGauss 1.X.X版本在企业版安装后会要求先改密码,2.0及以后的版本不需要。
- 数据库未启动。升级时要保证数据库处于正常运行状态。