将数据库从第一版本升级到第二版本的制作方法

文档序号:25352778发布日期:2021-06-08 13:59阅读:111来源:国知局
将数据库从第一版本升级到第二版本
背景技术
::1.数据库可以是有组织的数据集,所述数据集可以存储在存储器单元(即,存储设备)中并且可以通过由处理器控制的存储器控制电路系统来访问。数据库管理系统可以是可以由处理器操作的软件,以使得应用和最终用户可以与数据库的存储器单元进行交互。数据库管理系统也可以存储在数据库的存储器单元中。数据库管理系统可以被配置成使得存储在存储设备中的数据在与应用和最终用户交互中可以模仿被组织为一个或多个表。表可以是数据集,其中可以安排与一个或多个实体有关的一种或多种特定类型的数据组。特定类型的数据可以表示为表中的字段(即,列)。实体可以表示为表中的记录(即,行)。数据库管理系统可以被配置成:(1)创建记录以存储实体的数据,(2)将数据写入记录的一个或多个字段,(3)从记录的一个或多个字段中读取数据,以及(4)删除记录。附图说明2.附图结合在本说明书内并构成本说明书的一部分,所述附图被包括以提供对所公开的主题的进一步理解。附图还展示了所公开的主题的实施方式,并且与详细描述一起用于解释所公开的主题的实施方式的原理。没有试图更详细地示出可以其可以实践的各种方式和比基本理解所公开的主题所必需的结构细节。3.图1是展示数据库的实施例的图。4.图2是展示在时间t1的数据库的第一版本的状态的实施例的图。5.图3是展示在时间t2的数据库的第一版本的状态的实施例的图。6.图4是展示在时间t3的数据库的第二版本的状态的实施例的图。7.图5是展示将数据库升级到第二版本的常规操作的一部分的实施例的图。8.图6是展示数据库管理系统的第二版本的实施例的图。9.图7是展示将数据库升级到第二版本的常规操作的另一部分的实施例的图。10.图8是展示根据所公开的技术的将数据库升级到第二版本的操作的实施例的图。11.图9是展示用于数据库管理系统的第二版本的数据库目录的副本的实施例的图,所述数据库管理系统存储在正被用于数据库的第一版本的存储器单元中。12.图10是展示数据库管理系统的第二版本的图,所述数据库管理系统存储在正被用于数据库的第一版本的存储器单元中。13.图11是展示根据所公开的技术的用于将数据库从第一版本升级到第二版本的方法的实施例的流程图。14.图12是展示根据所公开的技术的用于将数据库从第一版本升级到第二版本的拓扑的实施例的图。15.图13是展示根据所公开的技术的用于将数据库从第一版本升级到第二版本的方法的实施例的图。16.图14是展示根据所公开的技术的用于将数据库从第一版本升级到第二版本的一些操作的实施例的流程图。17.图15是展示根据所公开的技术的用于创建影子目录的操作的实施例的流程图。18.图16是展示根据所公开的技术的用于错误和信号处理的操作的实施例的流程图。19.图17是展示了将数据库升级到第二版本的常规操作的实施例的图。20.图18是展示根据所公开的技术的将数据库升级到第二版本的操作的另一个实施例的图。21.图19是展示pg_class的实施例的图。22.图20是展示relmapper文件的实施例的图。23.图21是示出relfilenode的实施例的图。24.图22是展示根据所公开的技术的将数据库升级到第二版本的操作的又一实施例的图。25.图23是展示pg_catalog.pg_class中的样本数据的实施例的图。26.图24是展示根据所公开的技术的将数据库升级到第二版本的操作的仍另一个实施例的图。27.图25是展示在复制到影子目录之后pg_catalog.pg_class中的样本数据的实施例的图。28.图26是展示relfilenode互换的实施例的图。29.图27是展示影子目录升级的实施例的图。30.图28是展示高可用性(ha)升级的实施例的图。31.图29是展示灾难恢复(dr)升级的实施例的图。32.图30是展示管理符号链接的实施例的图。33.图31是展示刚好在重启之前管理符号链接的实施例的图。34.图32是展示重启之后管理符号链接的实施例的图。具体实施方式35.如本文所使用的,可以将“部件可以‘被配置成’执行操作”的陈述理解为意味着所述部件不需要结构上的改变,而仅需要置于操作状态(例如,提供有电力、具有运行的基础操作系统等)以执行所述操作。36.数据库可以是有组织的数据集,所述数据集可以存储在存储器单元(即,存储设备)中并且可以通过由处理器控制的存储器控制电路系统来访问。(例如,存储器单元可以在磁盘驱动器中。)数据库管理系统可以是可以由处理器操作的软件,以使得应用和最终用户可以与数据库的存储器单元进行交互。数据库管理系统也可以存储在数据库的存储器单元中。数据库管理系统可以被配置成使得存储在存储设备中的数据在与应用和最终用户交互中可以模仿、被组织为一个或多个表。表可以是数据集,其中可以安排与一个或多个实体有关的一种或多种特定类型的数据组。特定类型的数据可以表示为表中的字段(即,列)。实体可以表示为表中的记录(即,行)。数据库管理系统可以被配置成:(1)创建记录以存储实体的数据,(2)将数据写入记录的一个或多个字段,(3)从记录的一个或多个字段中读取数据,以及(4)删除记录。37.存储器单元的高效利用可以是数据库设计中的重要方面。可以安排表的设计以避免以下情形:一些存储器单元被指定成将特定项的数据存储在设计不良的表的字段中,但是仅少量记录包括该特定项的数据。可以使用第一表和第二表,而不是将此类数据存储在设计不良的表中。所述第一表可以存储与仅所述少量记录相关的特定项的数据,并且所述第二表可以存储剩余特定项的数据。可以在所述第一表与所述第二表之间建立关系,以使得可以从数据库中读取与仅所述少量记录相关的特定项的数据。元数据可以包括数据库中每个表的条目。每个条目可以包括表的名称,并且对于在所述表中所包括的每个字段,可以包括所述字段的名称以及存储在所述字段中的数据的类型。38.表的设计还可以被安排成避免以下情形:将特定项的数据重复地存储在设计不良的表的存储器单元中。可以再次使用第一表和第二表,而不是将此类数据存储在设计不良的表中。所述第一表可以配置成存储数据的仅单个实例,并且所述第二表可以存储剩余特定项的数据。再次,可以在所述第一表与所述第二表之间建立关系。39.尽管用于表设计的此种途径可以导致对存储器单元的高效利用,但是所述途径还可以导致大量的表以及这些大量的表之间的关系。相应地,数据库可以包括数据库目录,所述数据库目录可以存储元数据,所述元数据与在所述数据库中所包括的表的定义有关。所述元数据可以包括例如所述数据库中每个表的条目。每个条目可以包括例如表的名称,并且对于在所述表中所包括的每个字段,可以包括所述字段的名称以及存储在所述字段中的数据的类型。40.图1是展示数据库100的实施例的图。数据库100可以包括存储器单元102和处理器104。存储器单元102可以包括存储设备106,并且可以存储数据库管理系统108。数据库管理系统108可以包括一个或多个表110和数据库目录112。41.在配置中,存储器单元102可以在多租户数据库内。例如,多租户数据库可以包括第一组存储器单元102和第二组存储器单元102。第一组和第二组可以不相交。第一组可以被配置成存储第一组记录。第二组可以被配置成存储第二组记录。第一组记录的字段可以具有第二组记录的对应字段。第一组记录的字段中的字段可以是自定义字段。第二组记录的对应字段中的对应字段可以是对应自定义字段。可以将第一组记录的自定义字段指定成存储第一数据类型,而可以将第二组记录的对应自定义字段指定成存储第二数据类型。42.图2是展示在时间t1的数据库100的第一版本的状态的实施例的图。为了本文的示意性目的,数据库100可以用于小型信息技术支持服务公司。数据库100可以在时间t1包括“雇员证书”表、“活动日志”表(例如,图1中展示的一个或多个表110)以及“数据库目录”(例如,图1中展示的数据库目录112)。[0043]“雇员证书”表可以包括三个字段,并且在时间t1可以包括三个记录。这些字段可以包括“empid(雇员id)”、“姓名”和“证书”。三个记录在时间t1可以包括:(1)拥有雇员id001且是“苹果认证支持专家‑macos”的安妮·阿尔法(annealpha)的记录,(2)拥有雇员id002且是“思科认证技术员”的布莱恩·布拉沃(brianbravo)的记录,以及(3)拥有雇员id003且具有“oracle云认证”的辛迪·查尔斯(cindycharles)的记录。[0044]“活动日志”表可以包括三个字段,并且在时间t1可以包括三个记录。这些字段可以包括“时间戳”、“雇员id”和“活动”。在时间t1三个记录可以包括:(1)2018年8月15日下午3:03(时间戳201808151503)雇员id002为delta公司的排除网络故障所做的工作的记录,(2)2108年8月23日上午11:15(时间戳201808231115)雇员id001为eddieecho更新操作系统所做的工作的记录,以及(3)2018年8月27日下午1:42(时间戳201808271342)雇员id001为felicityfoxtrot更新操作系统所做的工作的记录。[0045]如在图2中所展示的,“雇员id”字段可以建立“雇员认证”表与“活动日志”表之间的关系。通过所述关系,查询数据库100可以确定:(1)“思科认证技术员”布莱恩·布拉沃执行了为delta公司网络排除故障的工作,以及(2)“苹果认证支持专家‑macos”安妮·阿尔法执行了为eddieecho和felicityfoxtrot更新操作系统的工作。[0046]“数据库目录”可以存储与“雇员认证”表的和“活动日志”表的定义有关的元数据。对于“雇员认证”表,元数据可以包括“表名称:雇员证书”、“字段名称:雇员id;数据类型:数字”、“字段名称:姓名;数据类型:文本”和“字段名称:认证;数据类型:文本”。对于“活动日志”表,元数据可以包括“表名称:活动日志”、“字段名称:时间戳;数据类型:日期”、“字段名称:雇员id;数据类型:数字”和“字段名称:活动;数据类型:文本”。[0047]当将数据添加到数据库中时,在较早时间导致存储器单元的高效利用的表的设计会在以后的时间导致所述存储器单元的低效利用。图3是展示在时间t2的数据库100的第一版本的状态的实施例的图。[0048]“雇员认证”表在时间t2可以包括自时间t1起添加的三个新记录:(4)具有雇员id002且现在还是“思科认证架构师”的布莱恩·布拉沃的记录,(5)具有雇员id003且现在还是“oracle数据库认证”的辛迪·查尔斯的记录,(6)具有雇员id001且现在还是“苹果认证支持专业人员–osx”的安妮·阿尔法的记录。[0049]“活动日志”表在时间t2可以包括自时间t1起添加的三个新记录:(4)2018年9月5日上午9:37(时间戳201809050937)雇员id003为高尔夫(golf)公司修改数据库所做的工作的记录,(5)2018年9月12日下午2:08(时间戳201809121408)雇员id001为亨利酒店(henryhotel)更新操作系统所做的工作的记录,以及(6)2018年9月20日下午12:10(时间戳201809201210)雇员id002为印度公司(indiacompany)排除网络故障所做的工作的记录。[0050]如在图2中所展示的,在时间t1导致存储器单元的高效利用的“雇员认证”表的设计在时间t2导致所述存储器单元的低效利用。在时间t2,在“雇员认证”表中,“姓名”字段的数据被重复存储。即,因为在时间t1,每个雇员仅有一个特定认证,所述在时间t1将具有特定认证的雇员的姓名数据存储在“雇员认证”表的“姓名”字段中导致了存储器单元的高效利用。然而,由于在时间t2,一个或多个雇员拥有一个或多个特定认证,因此将具有特定认证的雇员的姓名数据存储在“雇员认证”表的“姓名”字段中,导致存储器单元的低效利用。为了使得数据库100可以再次被配置用于存储器单元的高效利用,可以针对数据库100的第二版本重新安排表的设计。[0051]图4是展示在时间t3的数据库100的第二版本的状态的实施例的图。在时间t3,数据库100可以包括“认证”表、“雇员”表、“活动日志”表和“数据库目录”。[0052]“认证”表可以包括三个字段,并且在时间t3可以包括六个记录。这些字段可以包括“empid(雇员id)”、“certid(认证id)”和“认证”。“认证id”字段可以包括:(1)“苹果认证支持专家–macos”的认证idaaa,(2)“思科认证技术员”的认证idaab,(3)“oracle云认证”的认证idaac,(4)“思科认证架构师”的认证idaad,(5)“oracle数据库认证”的认证idaae,以及(6)“苹果认证支持专家–osx”的认证idaaf。这些对应于在时间t2在数据库100的第一版本中的包括在“雇员认证”表中的六个记录。[0053]“雇员”表可以包括两个字段,并且在时间t3可以包括三个记录。这些字段可以包括“雇员id”和“姓名”。在时间t3,三个记录可以包括:(1)安妮·阿尔法的记录,(2)布莱恩·布拉沃的记录,以及(3)辛迪·查尔斯的记录。[0054]在时间t3的数据库100的第二版本中的“活动日志”表可以与在时间t2的数据库100的第一版本中的“活动日志”表相同。[0055]如图3中所展示的,“雇员id”字段可以在“认证”表、“雇员”表与“活动日志”表之中建立关系。通过所述关系,查询数据库100可以确定:(1)“思科认证技术员”和“思科认证架构师”布莱恩·布拉沃为delta公司和印度公司执行了网络故障排除工作,(2)“苹果认证支持专家–macos”和“苹果认证支持专家–osx”安妮·阿尔法为eddieecho、felicityfoxtrot和亨利酒店执行了更新操作系统的工作,以及(3)拥有“oracle云认证”和“oracle数据库认证”的辛迪·查尔斯为高尔夫公司执行了修改数据库的工作。[0056]“数据库目录”可以存储与“认证”表的、“雇员”表的和“活动日志”表的定义有关的元数据。对于“认证”表,元数据可以包括“表名称:认证”、“字段名称:雇员id;数据类型:数字”、“字段名称:认证id;数据类型:文本”和“字段名称:认证;数据类型:文本”。对于“雇员”表,元数据可以包括“表名称:雇员”、“字段名称:雇员id;数据类型:数字”和“字段名称:名称;数据类型:文本”。对于“活动日志”表,元数据可以包括“表名称:活动日志”、“字段名称:时间戳;数据类型:日期”、“字段名称:雇员id;数据类型:数字”和“字段名称:活动;数据类型:文本”。[0057]所公开的技术可以涉及将数据库从第一版本升级到第二版本的操作。[0058]常规地,将数据库从第一版本升级到第二版本的操作需要:(1)提供另一个处理器和其他存储器单元来设计数据库管理系统的第二版本,(2)使所述数据库管理的所述第二版本系统与存储在存储设备中的数据进行交互,以及(3)终止所述数据库管理系统的第一版本的操作。这种途径需要相对大量的其他存储器单元以可用于存储数据库管理系统的第二版本,并且需要另一个处理器以可用于操作所述数据库管理系统的所述第二版本。[0059]图5是展示将数据库100升级到第二版本的常规操作的一部分的实施例的图。数据库100可以包括存储器单元102和处理器104。存储器单元102可以包括存储设备106,并且可以存储数据库管理系统108。数据库管理系统108可以包括数据库目录112和一个或多个表110。另外,数据库100可以包括另一个处理器504和其他存储器单元502,以设计数据库管理系统508的第二版本。数据库管理系统508的第二版本可以包括一个或多个其他表510(例如,在图4中展示的“认证”表、“雇员”表和“活动日志”表)和另一个数据库目录512(例如,图4中展示的“数据库目录”)。图6是展示数据库管理系统508的第二版本的实施例的图。[0060]图7是展示将数据库100升级到第二版本的常规操作的另一部分的实施例的图。如图7中所展示的,已经使数据库管理系统508的第二版本与存储在存储设备106中的数据进行交互以产生图4中所展示的数据库100的第二版本。在图7中展示的数据库具有共享存储设备。[0061]相比之下,不是:(1)提供另一个处理器和其他存储器单元来设计数据库管理系统的第二版本,以及(2)使所述数据库管理系统的所述第二版本与存储在存储设备中的数据进行交互,所公开的技术可以:(1)提供另一个处理器和其他存储器单元以产生用于数据库管理系统的第二版本的数据库目录,(2)在数据库的第一版本的存储器单元中建立第二版本控制器,(3)将用于所述数据库管理系统的所述第二版本的所述数据库目录的副本存储在所述数据库的所述第一版本的所述存储器单元中,(4)使所述第二版本控制器使用用于所述数据库管理系统的所述第二版本的所述数据库目录的所述副本来生成所述数据库管理系统的所述第二版本的一个或多个其他表,(5)使所述数据库管理系统的所述第二版本与存储在所述存储设备中的数据进行交互,以及(6)终止所述数据库管理系统的所述第一版本的操作。[0062]与上面描述的常规方法相比,所公开的技术的途径要求:(1)较少数量的其他存储器单元以可用于存储用于数据库管理系统的第二版本的数据库目录(而不是整个所述数据库管理系统的所述第二版本)和(2)由另一个处理器执行较少的操作,以产生用于数据库管理系统的第二版本的数据库目录(例如,与常规途径的另一个处理器相比,所公开的技术的另一个处理器可以是轻巧处理器)。另外,在配置中,可以逐步执行所公开的技术的操作,以使得:(1)由数据库提供给用户的服务中断仅能持续标称持续时间(例如,30秒),并且(2)可以以数据库用户无法察觉的方式有效地执行将数据库从第一版本升级到第二版本的操作。[0063]图8是展示根据所公开的技术的将数据库100升级到第二版本的操作的实施例的图。数据库100可以包括存储器单元102和处理器104。存储器单元102可以包括存储设备106,并且可以存储数据库管理系统108。数据库管理系统108可以包括数据库目录112和一个或多个表110。另外,数据库100可以包括另一个处理器804和其他存储器单元802,以产生用于数据库管理系统812的第二版本的数据库目录(例如,在图4展示的“数据库目录”),如图8中操作1所展示的。可以在正在被用于数据库100的第一版本的存储器单元102中建立第二版本控制器814,并且可以将用于数据库管理系统的第二版本的数据库目录的副本816存储在正被用于数据库100的第一版本的存储器单元102中,如图8中操作2所展示的。图9是展示用于数据库管理系统的第二版本的数据库目录的副本816的实施例的图,所述数据库管理系统存储在正被用于数据库100的第一版本的存储器单元102中。返回图8,可以使第二版本控制器814使用用于数据库管理系统的第二版本的数据库目录的副本816来产生所述数据库管理系统的所述第二版本的一个或多个其他表(例如,如在图4中所展示的“认证”表、“雇员”表和“活动日志”表),如图8中操作3所展示的。图10是展示数据库管理系统的第二版本的图,所述数据库管理系统存储在正被用于数据库100的第一版本的存储器单元102中。返回图8,可以使数据库管理系统的第二版本与存储在存储设备106中的数据进行交互以产生数据库100的(如图4中所展示的)第二版本,如图8中操作4所展示的。[0064]图11是展示根据所公开的技术的用于将数据库从第一版本升级到第二版本的方法1100的实施例的流程图。在方法1110中,在操作1102处,第一处理器可以产生用于数据库的数据库管理系统的第二版本的数据库目录。数据库目录可以被配置成存储元数据,所述元数据与数据库的第二版本中所包括的对象的或表的定义有关。与数据库的第二版本中所包括的对象的或表的定义有关的元数据可以包括例如用于所述数据库的所述第二版本中的每个对象的或表的条目。每个条目可以包括,例如:(1)表名称或对象名称和(2)对于所述表中所包括的每个字段或对于所述对象中所包括的每个属性:(a)字段名称或属性的名称和(b)储存在所述字段或所述属性中的数据类型。[0065]在操作1104处,可以使将在正被用于数据库的第一版本的存储器单元中建立控制器。例如,用于产生用于数据库管理系统的第二版本的数据库目录的存储器单元的数量可以小于用于数据库的第一版本的存储器单元的数量。[0066]在操作1106处,可以将用于数据库管理系统的第二版本的数据库目录的副本存储在用于数据库的第一版本的存储器单元中。[0067]在操作1108处,可以通过控制器使用数据库目录的副本、数据库管理系统的第二版本,来产生所述数据库管理系统的第二版本。控制器可以被配置成例如仅生成数据库管理系统的第二版本。控制器可以被配置成例如不生成数据库管理系统的另一个版本。[0068]在操作1110处,可以使数据库管理系统的第二版本与存储在数据库的存储设备中的数据进行交互。所述存储设备可以被包括在正被用于数据库的第一版本的存储器单元中。第二处理器可以被配置成例如与正被用于数据库的第一版本的存储器单元进行交互以操作所述数据库的所述第一版本。第一处理器可以不同于第二处理器。第一处理器的处理速度可以例如小于第二处理器的处理速度。在配置中,响应于访问存储在数据库的存储设备中的数据的一部分的请求,可以对所述数据的所述部分执行操作1110。以此方式,随着存储在数据库的存储设备中的数据的部分依次受到访问请求,所述数据库的升级可以随着时间的推移逐渐发生。可以以数据库用户无法察觉的方式来执行数据库的升级。[0069]在可选操作1112处,数据库的第一版本的操作可以终止。[0070]在配置中,实例的持续时间可以是较短的持续时间,在所述实例中,在升级数据库期间,所述数据库对请求无响应。例如,较短的持续时间可以小于或等于三十秒。[0071]在配置中,可以在升级数据库期间暂停升级与所述数据库相关联的应用。[0072]在配置中,可以针对数据库的第一集群执行操作1102、1104、1106、1108和1110。在该配置中,可以针对数据库的第二集群执行操作1102、1104、1106、1108和1110。例如,可以在已经针对数据库的第一集群执行了操作1102、1104、1106、1108和1110之后,发生针对数据库的第二集群执行操作1102、1104、1106、1108和1110。数据库的第二集群可以包括例如备用集群、灾难恢复集群或高可用性集群。[0073]根据所公开的技术,在任何给定时间每个主机可以运行一个数据库容器。这样可以最大程度地利用数据库主机。[0074]所公开的技术可以是足够通用的以处理绝大多数未来的数据库升级场景(即,需要中断的升级场景应相隔数年)。[0075]所公开的技术可能不会增加硬件要求(即,它们可能不需要额外的主机)。[0076]所公开的技术可以实现最终用户所感知的零停机时间。通常,这意味着数据库可以在最多30秒内不响应请求。[0077]所公开的技术在操作上可以是直接的。[0078]所公开的技术可以被配置成针对生产中的所有升级提供仅一种解决方案。[0079]可以以在数据库的升级期间可以暂停与所述数据库相关联的应用的升级的方式来实现所公开的技术。[0080]可以以使得正在进行的升级使高可用性(ha)服务或灾难恢复(dr)服务恶化的方式来实现所公开的技术。[0081]可以以使得升级的持续时间可以是可预测的并且在时间上接近恒定的方式实现所公开的技术。也就是说,对于较大的数据集,时间可能不会增加。[0082]可以以以下方式实现所公开的技术:使得如果升级由于任何原因而失败,则可以有简单的方法来返回到先前状态而不会丢失客户数据,并且总中断时间少于30秒。[0083]所公开的技术可以以一种容易或可行的方式实现,从而以自动化方式进行故障注入测试。[0084]所公开的技术可以建立影子数据库目录,在用更新版本替换数据库容器之前,所述影子数据库目录可以与升级版本匹配。当启动新的数据库二进制时,可以将旧目录换为新目录。[0085]使用公开的技术,将数据库服务集群从第一版本升级到第二版本可以包括以下操作:[0086]1.验证先决条件[0087]该阶段可以使整个升级过程中发生故障的风险最小化。它可以包括:[0088]a.清除来自先前失败的升级的残留。[0089]b.验证是否有充足的资源可用于包含转储的和复制的文件。[0090]c.确认没有正在进行的应用升级。[0091]2.建立新目录[0092]该操作可以由专用的“升级控制器容器”来执行,所述升级控制器容器可以驻留在sam中并且可以用于连接至主服务器(master)。控制器可以执行以下操作:[0093]a.可以在升级容器映像构建时间完成initdb(初始化数据库)。[0094]b.在数据库服务中创建影子目录模式。[0095]c.将数据库服务集群置于防止某些动作(以数据定义语言(ddl)编写)的模式。[0096]这可以将整个原始系统目录主要地置于只读模式。这可以排除pg_tenant。[0097]d.升级控制器可以执行数据库服务的app模式的转储。[0098]e.升级控制器可以执行将数据库服务的转储app模式还原到其本地数据库中。[0099]f.升级控制器可以将整个系统目录内容复制到一组csv文件中,并且为系统目录表生成ddl脚本。[0100]g.系统目录csv文件可以传送至数据库服务器主服务器。[0101]h.升级控制器可以用传送的csv文件填充(在b中创建的)影子目录表。[0102]i.升级控制器可以将数据库服务群集标记为“已准备好进行容器升级”。[0103]“升级控制器”可以用最少的数据库实例来执行,因为控制器的唯一目的是生成带有app模式的第二版系统目录。[0104]此外,控制器可以使用ram磁盘在存储器中完全运行,而无需进行日志记录。这可以大大提高还原性能。[0105]通过传送zip文件,可以将升级控制器与数据库服务器的主服务器之间传输的数据量保持在最低。转储输出和csv文件两者都可以很好地压缩。[0106]到此操作结束时,考虑到灾难恢复(dr)日志记录应用中的时延,整个数据库服务群集可以拥有最新的第二版本克隆目录。[0107]2.执行二进制升级。[0108]可以首先在灾难恢复(dr)位点和本地数据库服务器的从服务器上执行该操作。[0109]可以依靠高可用性(ha)故障转移来最后升级主服务器,以保持应用正常运行。注意,此时,app可以开始在第二版数据库二进制上运行。[0110]各个操作可以是:[0111]a.用第二版本容器替换第一版本容器。[0112]b.启动数据库的第二版本。[0113]c.当数据库的第二版本启动时,它将发现它是第二版本,并且所述第二版本存在目录克隆。[0114]然后,它可以翻转目录以使用该克隆,并且可以对引导程序表执行少量内务处理。[0115]d.进入连续复原模式(即,这可以始终是从服务器)。[0116]3.删除no‑ddl(无ddl)标志。[0117]一旦集群中的最后一个节点已经升级后,可以再次允许某些动作(以ddl编写)。[0118]升级控制器服务器[0119]升级控制器可以是无需与数据库节点协同定位的微服务器。从概念上讲,它可以是编制的一部分。容器可以包括:[0120]·数据库的第二版本实例。(注意,这随每个版本变化,因此每次升级都可能需要产生一个新的控制器(控制器可以只是空的initdb,因此它本身不会升级)。)[0121]·可选地,ram磁盘足够大以保存核心app模式。替代性地,可以使用本地ssd。[0122]·执行升级步骤的驱动程序[0123]可能不需要:[0124]·java虚拟机(jvm),[0125]·公制流式传输器,或者[0126]·分布式数据库存储装置。[0127]在配置中,容器可以带有已经执行准备接受app模式的initdb。[0128]图12是展示根据所公开的技术的用于将数据库从第一版本升级到第二版本的拓扑的实施例的图。[0129]图13是展示根据所公开的技术的用于将数据库从第一版本升级到第二版本的方法的实施例的图。在图13中展示出了以下操作:[0130]1.获取第二版本控制器(即,用于此特定升级版本的控制器)[0131]2.转储第二版系统目录ddl文件[0132](initdb之后的控制器第二版本目录的pg_dump)[0133]3.将目录ddl文件(来自步骤2的pg_dump输出)推送到主服务器[0134]4.对于每个数据库,在第一版本主服务器上以新模式构建第二版本影子目录。共享表只能在template1中构建一次。[0135]5.标记no‑ddl阶段(从控制器上的升级脚本调用)[0136]a.这可以停止工作流守护进程,或者它们必须遵守restrict‑ddl(约束‑ddl)语义。但是,dr位点工作流守护程序可能继续,因为它们从不修改目录表。[0137]6.转储不包括影子表的app模式ddl。[0138]7.将app模式ddl拉到控制器[0139]8.将app模式还原到第二版本目录(在控制器上)[0140]9.将第二版本目录复制到逗号分隔值(csv)文件[0141]10.将csv文件传送到主服务器[0142]11.将csv文件复制到第二版本影子目录[0143]12.将数据库标记为准备好升级[0144]13.在灾难恢复(dr)位点上执行kubernetes升级[0145]a.等待影子目录传播到灾难恢复(dr)位点[0146]b.启动第二版本从服务器(其查找并使用影子目录)[0147]c.当所有从服务器都以第二版本运行时,刷新(以完成大部分工作),进入仅超级用户模式(以停止app连接),刷新(以加速复原),停止第一版本主服务器[0148]14.在主位点(primarysite)上执行kubernetes升级[0149]a.启动第二版本从服务器(其查找并使用影子目录)[0150]b.当所有从服务器都是第二版本时,刷新(以完成大部分工作),进入仅超级用户模式(以停止app连接),刷新(以加速复原),停止第一版本主服务器[0151]15.清除restrict‑ddl模式(由编制器调用以进行成功升级或失败升级)[0152]16.升级后的数据库现在可以使用了[0153]技术细节[0154]数据库升级可以分为两个主要阶段。[0155]影子目录创建。此阶段可以隐藏目录更改的详情,使得滚动升级的下一个阶段可以进行二进制升级。此阶段可以由升级控制器、轻巧的(仅sdb映像,无bk代理和公制流式传输器)短暂的容器来处理,所述容器可以包含数据库映像的第二版本和升级脚本。每个数据库集群可以需要一个升级控制器。在成功完成此阶段之后,可以在主数据库(primary)中创建具有第二版本形状(shape)、内置的和app模式的影子目录。当备用数据库(standby)赶上影子目录更改时,集群可以准备升级。如果此阶段无论如何失败了,也不会造成伤害。此阶段创建的所有内容都是只能与第二版本映像一起使用的影子目录。当升级控制器再次运行时,可以丢弃先前失败运行遗留的任何制品(artifact)。对于核心app模式和2gb存储器,此阶段要花费大约10分钟。[0156]滚动升级。此阶段与编制相关联。升级可以首先在生产集群上发生,并且最后在灾难恢复(dr)集群上发生。[0157]创建影子目录[0158]升级模式。数据库升级可以需要通常不允许的操作,包括创建影子模式和在pg_global表空间中创建表。添加新的布尔会话范围“大统一配置(grandunifiedconfiguration,guc)”,以在升级中允许这些。guc只能由超级用户设置。升级控制器可以作为db超级用户来执行数据库集群中的脚本。[0159]阻止某些数据库动作(以ddl编写)。大多数操作可以迭代pg_database中的所有数据库。这样,一旦已获得了要处理的数据库列表,就有必要阻止某些数据库动作(以ddl编写)。命令可以是:selectpg_catalog.pg_set_restriction_mode('block‑db‑ddl');[0160]影子模式。影子目录表可以在超级用户拥有的名为sdb_shadow_catalog的模式下创建。所述名称只能保留供数据库升级使用。为了安全起见,应用不能创建相同的模式或修改其内容。这假设应用无法通过超级用户连接到数据库。对于故障诊断,所述模式对于以超级用户身份连接的发布工程师可见。[0161]可以在集群中的每个数据库中创建(或者如果已有的话,则首先丢弃)模式。默认情况下,template0不允许连接。它可能在升级期间启用连接,并且在最后禁用。[0162]影子目录表。大多数目录表可以特定于数据库,例如pg_class。可以像普通用户表一样创建用于这些数据库的影子表。[0163]一小组目录表的可以由所有数据库共享,例如pg_database、pg_authid、pg_tenant等。这些表行的日志结构合并(lsm)键的数据库编号部分为0。影子表可以需要特定tweek。它的键必须与最终将要替换的真实键在相同的键空间中。这意味着数据库编号也可以是0。要做到此的方法可以是在创建表ddl中使用pg_global表空间。例如,createtablesdb_shadow_catalog.pg_database(...)withoidstablespacepg_global;[0164]表空间未在数据库中使用。在这里,使用pg_global只能获得正确的存储设备键,而无需发明新的语法。[0165]可以从psql\d表命令输出中解析用于创建影子目录的ddl。pg_dump可能无法立即起作用,因为主键未正确转储,并且lsm表需要主键。这可能是因为目录表没有在pg_constraint表中定义的主键约束。结果,可以将主键作为唯一索引转储。pg_dump可以是固定的。pg_dump‑‑table=pg_class‑‑schema‑onlytemplate1[0166]createlsmtablepg_class([0167]relnamenamenotnull,[0168]relnamespaceoidnotnull,[0169]reltypeoidnotnull,[0170]reloftypeoidnotnull,[0171]relowneroidnotnull,[0172]relamoidnotnull,[0173]relfilenodeoidnotnull,[0174]reltablespaceoidnotnull,[0175]relpages_deprecatedintegernotnull,[0176]reltuples_deprecatedrealnotnull,[0177]relallvisibleintegernotnull,[0178]reltoastrelidoidnotnull,[0179]relhasindexbooleannotnull,[0180]relissharedbooleannotnull,[0181]relpersistence"char"notnull,[0182]relkind"char"notnull,[0183]reltenancy"char"notnull,[0184]relnattssmallintnotnull,[0185]relcheckssmallintnotnull,[0186]relhasoidsbooleannotnull,[0187]relhaspkeybooleannotnull,[0188]relhasrulesbooleannotnull,[0189]relhastriggersbooleannotnull,[0190]relhassubclassbooleannotnull,[0191]relrowsecuritybooleannotnull,[0192]relforcerowsecuritybooleannotnull,[0193]relispopulatedbooleannotnull[0194]relreplident"char"notnull,[0195]relfrozenxidxidnotnull,[0196]relminmxidxidnotnull,[0197]relaclaclitem[],[0198]reloptionstext[][0199]);[0200]createuniqueindexpg_classonpg_classusinglsm(oid);[0201]createuniqueindexpg_class_relname_nsp_indexonpg_classusinglsm(relname,relnamespace);[0202]createindexpg_class_tblspc_relfilenode_indexonpg_classusinglsm(reltablespace,relfilenode);[0203]pg_tenant[0204]如果表pg_tenant的形状不改变,则它可能不是影子目录的一部分,因为它可能不必要地阻止租户操作。这是影子目录升级优于sdbinstall的优点之一,sdbinstall需要复制每个目录表。在它确实改变的罕见情况下,可以将其添加到影子表中。sdbinstall可以将租户转储与其他模式转储分开,以减少阻止租户操作的窗口。在将其他ddl文件复制到影子模式之后,系统也可以阻止租户ddl文件。然后可以用相同的方式将pg_tenant复制到影子模式中。[0205]替代性地,所公开的技术可以通过预定义将来要使用的n(例如,30)个文本列(如sfdc核心中的自定义对象),而不对pg_tenant进行改变。pg_tenant表可能永远不会被遮盖。然而,当改变或添加索引时,此方法可以有并发症。影子表可以自动处理索引改变。[0206]pg_statistic[0207]即使pg_statistic表的形状不改变,也需要对其进行消隐,因为它的anyarray类型列包含pg_type.oid,这对于information_schema.sql中定义的一些类型是不稳定的。有关如何处理pg_statistic的详细信息,请参见anyarray。[0208]pg_workflow[0209]工作流数据可以在pg_workflow和pg_workflow_tags中。可以使用与sdbinstall相同的直接dml语句来处理向控制器的导入。活动工作流也可以在存储设备目录中。sdbinstall使用sql函数来在存储设备目录中导出和导入工作流。影子目录不需要此操作,因为它是就地升级。可以对存储设备目录进行版本控制。第二版本可以能够读取相同的存储设备目录(连同其中的工作流)并且转换为最新版本。[0210]当前可以使用工作流来创建索引和租户快照。默认情况下,升级期间可以阻止工作流执行,因为它可能改变系统目录,从而致使影子目录无效。然而,在升级期间不阻止租户快照可以是重要的。可以使用与pg_tenant相同的途径。如果形状没有改变,则工作流表可能不会被消隐。[0211]序列[0212]pg_workflowid和pg_lsmoid是可以在initdb期间创建的目录序列。它们的oid/relfilenode可能不稳定。[0213]也可能需要为它们创建影子序列。[0214]1.增强pg_dump以输出序列定义和当前值。[0215]2.创建影子序列,并且将当前值设置为来自转储的相同值。[0216]3.像影子表一样更新序列的relfilenode[0217]用户定义序列可以就像用户定义表一样使用,因为relfilenode不会改变。然而,重要的假设是序列的存储格式不得改变(或向后兼容)。可以将序列存储为日志结构合并(lsm)中的单个元组,所述单个元组具有存储序列元数据(如起始值、增量等)以及最后值的几个硬编码属性。如果postgres以某种方式改变了格式,则将中断此升级。pg10中可能会发生这种情况。在pg10中,序列记录格式发生了显著变化(将一些属性从数据记录移至pg_sequence表)。为了使升级生效,数据库可以通过将移至数据记录中pg_sequence的属性保持为伪值来与pg10脱离。[0218]无ddl模式[0219]创建影子模式后,数据库可以进入无ddl模式。租户仍可以创建、修改或丢弃。该模式可以是持久性的(用于template1行的pg_database.datrmode列),并且可以阻止来自app/后端或守护进程的所有ddl文件(期望创建租户/丢弃租户)。[0220]同时,也可以暂停工作流程,以确保影子中的副本与原始完全相同。[0221]模式转储和还原[0222]pg_dumpall可用于转储所有app模式,影子目录模式除外。因此,将转储文件加载到影子目录中时,可能没有影子目录信息。例如,pg_catalog.pg_class具有用于sdb_shadow_catalog.pg_class的行时,sdb_shadow_catalog.pg_class没有。因此,升级后可以不需要清理影子目录元数据。[0223]当前,pg_dumpall不转储template0、template1和postgres。这意味着升级后可以不会转入对这些数据库的任何自定义设置。[0224]来自数据库核心app的模式转储大小为约180mb,并且在发送到控制器之前可以压缩到20mb。测试显示,模式转储在本地可以花费50秒,如果从其他主机进行转储则花费3分钟。最好使用ssh进入主服务器来运行转储命令。[0225]可以通过psql在控制器中重播转储文件。[0226]复制目录数据[0227]接下来,使用复制命令将目录表数据从第二版本控制器复制到数据库集群中的影子目录,所述数据库集群仍在每个数据库的第一版本中运行。如果表具有oid,则可以对其进行维护,以使得fk引用保持有效。[0228]在控制器上[0229]copypg_classto“<filepath>”withoids;[0230]在主服务器上[0231]copysdb_shadow_catalog.pg_classfrom“<filepath>”withoids;[0232]所公开的技术可以确保从“copyto(复制至)”中的第二版本生成的文本或二进制数据可以在“copyfrom(复制自)”中的第一版本中被正确读取。<adt>在和<adt>在内部格式与外部格式之间转换的<adt>in函数和<adt>out函数必须在各个发行版中匹配。复制命令文档指示二进制输出格式的向后兼容性。由于阅读器(主服务器)在较旧的版本上,因此所公开的技术会需要向前兼容。可以使用文本格式。这会是需要良好测试的风险领域,尤其对于复杂数据类型,如anyarray、pg_node_tree、aclitem。一个简单的测试可以是将第二版本副本输出与第一版本副本输出进行比较。[0233]pg_catalog表中唯一列数据类型的列表。[0234]ppostgres=#selectdistinctatttypid::regtypefrompg_attributea,[0235]pg_classcwherea.attrelid=c.oidandc.relnamespace='pg_catalog'::regnamespaceandc.relkind=’r’;[0236]atttypid[0237]‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑[0238]text[0239]oid[0240]“char”[0241]pg_node_tree[0242]带时区的时间戳[0243]aclitem[][0244]boolean[0245]anyarray[0246]oid[][0247]gkey[0248]int2vector[0249]regproc[0250]smallint[][0251]xid[0252]bytea[0253]“char”[][0254]real[][0255]oidvector[0256]real[0257]name[0258]cid[0259]smallint[0260]integer[0261]bigint[0262]text[][0263](25行)[0264]anyarray[0265]pg_statistic中使用的anyarray类型可能很棘手。由于可以是任何类型,因此文本输出具有pg_typeoid来标识后跟有数组值的类型。然而,对于没有指定oid的类型(例log消息(诸如lsmlock、lsminvalidate)的一部分。[0280]4.调整复制命令以重新映射oid。除了pg_database中的、pg_tenant中的主键外,还可以在pg_replication_slots.datoid(可能其他)中引用数据库oid。不利之处可能是容易丢失现有的/新的数据库oidfk列。oid矢量类型会很难处理。[0281]relfilenode和映射文件[0282]在此阶段,可以创建影子目录表并填充数据。[0283]pg_catalog.pg_class中的样本数据[0284][0285]匹配sdb_shadow_catalog.pg_class中的数据[0286][0287]对于大多数表和索引,关系的物理位置id可以存储在pg_class.relfilenode列中,对于一小组引导程序关系,可以存储在pg_filenode.map文件中。这些一起可以指定目录。填充影子目录后,可以更新影子pg_class中的relfilenode。[0288]‑‑在等效的影子目录pg_class中,更新relfilenode[0289]ppg_***tothematchingshadowone[0290]updatesdb_shadow_catalog.pg_classo[0291]setrelfilenode=([0292]selectn.relfilenode[0293]frompg_catalog.pg_classn[0294]wheren.relnamespace='sdb_shadow_catalog'::regnamespace[0295]andn.relname=o.relname[0296])[0297]whereo.relnamespace='pg_catalog'::regnamespace[0298]ando.relfilenode!=0[0299]andexists([0300]selectn.relfilenode[0301]frompg_catalog.pg_classn[0302]wheren.relnamespace='sdb_shadow_catalog'::regnamespaceandn.relname=o.relname);[0303]类似于shadow_splice()的新函数可以用于在与pg_filenode.map相同的目录中生成名为pg_filenode.map.shadow的第二版本pg_filenode.map文件。[0304]selectcreate_shadow_relmapper(false,aa,‘catversion’)from([0305]select('{'||string_agg(array_to_string(array[o.oid,[0306]n.relfilenode,o.relam],','),',')||'}')::oid[]asaafromsdb_shadow_catalog.pg_classo,pg_catalog.pg_classnwhereo.relnamespace='pg_catalog'::regnamespace[0307]ando.relfilenode=0[0308]ando.relisshared=false[0309]andn.relnamespace='sdb_shadow_catalog'::regnamespaceandn.relname=o.relname);name);[0310]此查询遍历第二版本映射的目录关系(aliaso)。[0311]1.如果存在影子表(除pg_tenant及其索引以外的所有关系均为true),则可以更新映射器文件以使用影子关系的位置。[0312]2.如果没有影子表(pg_tenant),则行映射器文件可能不会更新。隐含的假设是pg_tenant的relfilenode永远不会改变。[0313]3.可能不会由此查询处理的一个极端情况是第二版本删除一些映射关系时。由于create_shadow_relmapper使用第一版本映射器文件作为起点(使得上面的情况2可以起作用),从第二版本中删除的任何关系都可能不会从映射器文件中删除。[0314]重要[0315]可以假设的是对于没有被消隐的表(pg_tenant,仅现在),relfilenode字段永远不会更改(例如,pg_tenantrelfilenode为2619。如果在第二版本中将其更改为3000,那么它将在位置3000中查找,而实际数据位于2619。这可以是关键的。相应地,可以为此使用回归测试)。[0316]由于函数只能在本地生成新文件,因此所述函数不会创建任何日志记录,并且无法在备用数据库中自动重播。选项可以是:[0317]1.连接到每个容器以执行该函数。对于所有备用数据库,可能需要等到日志被捕获后再执行该函数(通过将备用数据库中的pg_get_system_visible_xcn与主数据库中的pg_get_session_snapshot_xcn()进行比较?)。[0318]2.记录它,以便可以在所有备用数据库上重播它。文件可以恰好是1024个字节。[0319]3.首先启动sdb_basebackup,然后再启动第二版本的容器。可以依靠它将文件传播到备用数据库。然而,如果主服务器崩溃,则新的映射器文件可能会随之消失。另外,灾难恢复(dr)备用数据库只能连接到没有映射器文件的dr主服务器。[0320]4.zookeeper,但每个数据中心将拥有自己的zookeeper集群,仍需要跨数据中心消息传送。[0321]在公开的技术中,第二选择可以是优选的。[0322]这里重要的假设是,映射文件格式在第一版本与第二版本之间不改变。由于影子映射文件是从第一版本写入的,但是由第二版本使用,因此如果格式改变了,则第二版本可能无法读取所述文件。重命名为pg_filenode.map之前,可能需要将影子映射器文件转换为第二版本格式。可以使用单独转换器可执行程序(executable)。[0323]在用于基于容器部署的sdbdockerrepo中,可以在升级时擦除pgdata并且通过使用sdb_basebackup与主服务器同步来重新创建pgdata。[0324]清理过时目录[0325]数据库核心可以生成例如180mb的目录数据。在肯定不再需要这些旧目录数据后,便可以对其进行清理。最早的此种时间可以是在第二版本的主服务器成功完成升级时。因为在那时可以禁止回滚,所以可以安全地删除旧目录。[0326]第二版本出现后,旧目录不会立即删除。这种途径可以简化崩溃处理并且可以具有检验价值。[0327]·可以保留固定数量(例如,2个)的旧目录,每个都具有自己的模式,sdb_obsolete_catalog_<unixepochtimestamp>。[0328]·升级首先检查此类模式的数量是否已达到限制。如果是这样,升级删除最旧的模式。这是实际上可以删除旧目录的时间。[0329]·可以创建一个具有命名约定的新模式。可以在其中创建空的第一版本目录表/索引/序列。[0330]·relfilenode可以与第二版本影子目录交换。[0331]升级前pg_catalog.pg_class中的样本行[0332][0333][0334]升级期间pg_catalog.pg_class中的样本行[0335]删除模式sdb_obsolete_catalog_1111111[0336]创建模式sdb_obsolete_catalog_1111113、sdb_shadow_catalog[0337][0338]relfilenode交换之前的升级期间sdb_shadow_catalog.pg_class中的样本行[0339][0340][0341]relfilenode交换后的升级期间sdb_shadow_catalog.pg_class中的样本行[0342][0343]途径可以允许多个旧目录。然而,转储时间和加载时间会随每个副本线性增加。为了性能,只能保留一个过时模式副本,直到下一次升级为止。下次升级可以首先丢弃旧目录,因此pg_dump时间可以不会受到不利影响。由于只有一个副本,因此模式名称中可以不需要时间戳后缀。[0344]pg_control/pg‑version[0345]pgdata/global下的二进制文件pg_control可以具有许多字段。pg_control_version和catalog_version_no这两个字段对于升级很重要。可以在开始postgres时检查这些值,并且如果它们与可执行程序不匹配,则启动失败。[0346]还可以是pgdata下的pg_version文本文件和每个数据库子目录pgdata/base/<dbid>。也可以检查它们。[0347]因此,需要在现有pgdata上运行第二版本之前更新这些文件。这类似于将pg_filenode.map.shadow重命名为pg_filenode.map。编制器可以处理此问题。[0348]1.关闭第一版本容器。[0349]2.制作其pgdata的副本以供第二版本使用(也可以从主服务器进行sdb_basebackup)。[0350]3.在副本中:[0351]a.将pg_filenode.map.shadow重命名为pg_filenode.map[0352]b.更新pg_version文件(每当执行来自社区的合并时需要)[0353]c.如下面所描述的将pg_control_version和catalog_version_no移出至存储设备目录。[0354]2.在匹配的pgdata上启动第二版本容器[0355]替代性地,可以不需要pgdata,而仅将基本数据移至存储目录。[0356]存储设备目录改变[0357]系统目录号和sdb版本号可以存储在存储目录中。[0358]sdb_version_num301079000[0359]system_catalog_num201802070[0360]sdb_version_num0[0361]system_catalog_num0[0362]这些值可以是允许的系统目录号。只有具有匹配系统目录号的数据库可执行程序才能启动。可以有两个插槽,因为在升级期间,集群可能具有正在运行的两个数据库版本(例如,第二版本的高可用性,第一版本的主数据库)。[0363]·initdb使用当前数据库和目录版本填充插槽1。[0364]·数据库服务器启动时,它使用来自存储设备目录中的值来检查其目录号,并且如果其目录号与系统目录号不匹配,则会出错。[0365]·执行升级时,主服务器可以在另一个插槽中设置第二版本目录号。<catalog_number,release_number>对于升级必须唯一。[0366]·当主服务器在第二版本上启动时,它将重置包含旧目录号的插槽。[0367]·改变引入了更加限制性的检查。以前,数据库二进制检查和pgdata兼容性检查是基于pg版本(例如,9.6)和目录版本的。现在,它们基于数据库版本和目录版本。这可以意味着(例如,仅通过服务器退回)阻止直接降级。然而,如果期望此动作,则用sql函数将版本添加到存储设备目录中。技术实现要素:[0368]创建影子目录的步骤:[0369]1.验证源数据库处于要升级的状态[0370]2.启动控制器[0371]3.阻止创建/丢弃/更改某些数据库ddl文件[0372]4.启用template0的datallowconn[0373]5.在源数据库和控制器数据库中两者中暂停工作流[0374]6.创建具有第二版本的配置(即,形状)的sdb_shadow_catalog模式[0375]7.创建具有第一版本的配置(即,形状)的sdb_obsolete_catalog模式[0376]8.阻止某些ddl文件(租户除外)[0377]9.转储app模式[0378]10.将app模式加载到控制器中[0379]11.将工作流从源转储并加载到控制器[0380]12.将目录表从控制器复制到影子表[0381]13.如果租户配置(即,形状)已改变,则将租户转储并加载到影子pg_tenant[0382]14.生成影子pg_filenode.map,更新用于目录关系的sdb_shadow_catalog.pg_class中的relfilenode指针[0383]图14是展示根据所公开的技术的用于将数据库从第一版本升级到第二版本的一些操作的实施例的流程图。[0384]图15是展示根据所公开的技术的用于创建影子目录的操作的实施例的流程图。[0385]图16是展示根据所公开的技术的用于错误和信号处理的操作的实施例的流程图。[0386]测试[0387]目录数据修正[0388]目录数据可以包括pg_catalog模式下的所有内容、形状和内容两者。可以通过检查来自新安装的数据库的pg_dump输出和升级的数据库来进行测试。[0389]1.安装第一版本,在所述第一版本中设置一些模式,运行升级。[0390]2.使用第二版本安装新数据库并且设置相同的模式[0391]3.使用pg_dump‑‑schema=pg_catalog从两个版本中转储目录模式,并且使用pg_dumpall‑‑schema‑only从两个版本中转储app模式,并进行比较。它们应该是相同的。[0392]数据修正[0393]升级不会触碰用户表数据。测试可以验证relfilenode没有更改,并且转储一些测试表。[0394]限制[0395]升级完成后,限制模式、工作流暂停,并且template0连通性都应设置回原始值。升级成功和升级失败时都可以对它们进行测试。[0396]删除旧目录[0397]升级之前,请保存用于目录关系的relfilenode。升级后,请检查此类relfilenode在日志结构合并(lsm)中是否没有数据。[0398]故障案例[0399]任何故障发生时,都可以中止升级。一些故障案例可以包括:[0400]1.主服务器崩溃[0401]2.控制器崩溃[0402]3.失去主服务器身份[0403]4.网络错误/磁盘错误[0404]5.升级脚本崩溃/编制器崩溃[0405]升级脚本将尝试退出数据库限制模式(no‑ddl、nodb、notenant等),并且复原template0的连接设置。然而,当主服务器崩溃时,这样做可能并不总是可行的。数据库恢复后,操作员有两种选择:[0406]·调用清除函数以退出限制模式(在配置中,每当启动/升级主服务器时,都可以自动完成此操作)。[0407]·重试升级。日志和制品(例如,部分完成的影子目录)可以用于诊断问题。[0408]app测试[0409]可以在升级前后运行一组app测试(当前预签入),并且验证升级后故障的测试是升级前故障的子集。比预签入(例如,基本ftest)更全面的套件会更好。[0410]性能测试[0411]1除升级本身之外的测试。这可以测试升级后的数据库没有性能劣化。[0412]2测试升级本身。[0413]app开发人员特定测试[0414]1.多个app分支(例如,214个主分支)[0415]2.将由升级支持的每个数据库版本作为源版本(301.84)进行测试[0416]3.数据库ant/blt目标[0417]a.sdb.start[0418]b.sdb.stop[0419]c.sdb.ngupgrade[0420]d.sdb.ngupgrade_maybe[0421]e.sdb.rollback_ngupgrade[0422]4.osx和ubuntu两者[0423]5.破坏性测试[0424]a.升级失败时,用户仍可以使用第一版本数据库。[0425]6.清理过时的数据区(extent)[0426]a.由于sdb_basebackup可用于在升级期间备份数据库,因此可以在不再需要时删除过时的数据。[0427]备份[0428]由于升级或新的第二版本二进制都有机会损坏数据,因此在更新之前备份数据库非常重要。sdb_basebackup可用于创建备份。在sfstore上,可以使用克隆选项。它可以更快,因为它仅需要复制最新的日志区。对于pgfilestore上的app开发人员(appdev),较快的克隆选项可能不起作用。较慢的备份选项可以复制所有数据区/日志区。备份可以在升级开始时与创建影子目录同时运行。在具有ssd的开发箱上进行的测试显示出,备份吞吐量可以为大约1gb/10秒,或者在创建影子目录所花费的时间(大约10分钟)内为大约60gb。[0429]pg10挑战[0430]一些pg10改变会中断影子目录升级。问题和解决方案列表可以包括:[0431]1.新的pg_data布局:将pg_clog重命名为pg_xact,并且将pg_xlog重命名为pg_wal。解决方案:在旧的pgdata中重命名相同的目录。[0432]2.pg_control文件格式改变。已添加新的安全性字段mock_authentication_nonce。解决方案:创建可以升级pg_control文件的新二进制。[0433]3.xlog页魔术数字(pagemagicnumber)改变。似乎postgres在每个主要版本中都会改变魔术数字。postgres不想新的二进制在旧数据库上运行。解决方案:下一代升级可以使用相同的xlog文件。xlog页魔术数字不需要保持稳定。这是一个短期修复,如果下一个社区版本中的xlog格式发生改变,则会存在问题。长期的解决方案可以是摆脱社区xlog,并且在更大的情景中,摆脱整个pgdata目录。在大多数情况下,数据库不使用社区xlog。数据库仍会写入从postgres继承的某些记录(例如,dbshutdown)。[0434]4.新的目录数据类型。这通常会需要从postgres中精选新类型和新的版本壁垒。解决方案:在pg10的情况下,可以将新类型、pg_ndistict和pg_dependencies强制转换为bytea类型。[0435]5.新的默认角色。一些目录列是aclitem[]类型。aclitem在其in函数/out函数中验证角色名称。这会中断升级,因为从pg10中转储了aclitem并且在pg9.6中可能不被接受。解决方案:原始字节可以直接在复制命令中进行base64编码/解码。这可以包括所有数组类型。这可以允许跳过验证,这是可以接受的,因为数据打算由第二版本的二进制使用。[0436]滚动升级[0437]滚动升级可以从主数据库开始。[0438]1.停止第一版本备用容器(容器内的pgdata可以安装到主机上,并且在关闭后移至临时目录(tempdir))。[0439]2.在相同节点上启动第二版本容器[0440]a.可以从sdb_basebackup获取影子relmapper文件(以其他方式,可能需要等待备用数据库来赶上并且根据日志记录创建影子relmapper)[0441]b.影子relmapper文件可以重命名为pg_filenode.map[0442]3.可以对所有备用数据库重复以上操作[0443]4.主数据库可以停止,故障转移到备用数据库[0444]5.新升级的第二版本主服务器可以使用其版本创建日志记录。如果备用版本较旧,则备用数据库可以暂停日志重播。[0445]6.可以将旧的主数据库重新启动为备用数据库。主位点可以完成。[0446]7.可以在灾难恢复(dr)位点上重复上述操作[0447]升级后[0448]升级后的动作可以包括:[0449]·退出无ddl模式[0450]·删除旧目录[0451]·执行任何验证[0452]错误处理[0453]此新升级的首次展示可以是向app开发人员。初始实施方式可以在python中进行。python升级脚本可以处理包括服务器重启的整个过程,并且可以替换基于sdbinstall的sdb升级。[0454]升级期间的任何时候都可能会出现故障和崩溃。崩溃可以是脚本意外停止运行时(例如,断电等)或无法连接到数据库(例如,网络问题、关机)。在此种情况下,脚本无法执行清理工作。故障可以包括所有可能进行清除的其他情况。故障可以自动处理,而崩溃会需要通过调用ant目标来进行手动清除。(在配置中,可以使用sdb.start调用清除,使得不需要手动清除)。[0455]在影子目录创建期间[0456]制品:[0457]1.模式:sdb_shadow_catalog、sdb_obsolete_catalog[0458]2.template0.datallowconn设置[0459]3.数据库限制模式(pg_database.rmode)[0460]4.工作流暂停模式[0461]5.控制器sdb实例[0462]故障:撤消上述操作2、3、4和5。可以保留模式而不会造成伤害,并且在下一次运行时对其进行清除。[0463]崩溃:用户可以调用ant目标来撤消操作2、3和4(现在是sdb.startant目标的一部分)。如果升级控制器仍在运行,则需要手动将其关闭。在配置中,数据库可以自动执行此操作。[0464]服务器重启期间[0465]动作:[0466]1.清空第一版本[0467]2.将新版本号添加到存储目录[0468]3.停止第一版本[0469]4.将第一版本pgdata复制成第二版本(cp~/sdb/sdbdata/<cluuid>~/sdb/sdbdata/<cluuid>_v2)。如果使用sdb_basebackup,则可能已经存在从第一版本克隆的pgdata。[0470]5.更新第二版本的pgdata(relmapper文件、pg_version文件和postgresql.conf)[0471]6.启动第二版本[0472]错误处理可以与影子目录创建相同[0473]升级后[0474]动作:[0475]7.可选地,从存储目录中移除旧版本号[0476]8.停止控制器(异步,忽略结果)[0477]9.更新当前二进制和pgdata符号链接两者。可以在python脚本之外通过caller(ant)进行管理。[0478]a.~/sdb/sdbbuild/current[0479]b.~/sdb/sdbbuild/current.previous[0480]c.~/sdb/sdbdata/sdbmain[0481]d.~/sdb/sdbdata/sdbmain.previous[0482]崩溃:[0483]在操作7之前/期间:移除存储目录中的版本号并不重要。[0484]操作8之前/期间:控制器可以保持运行状态。用户可能需要手动停止它。[0485]回滚[0486]在第二版本或升级脚本本身存在严重问题的情况下,可以允许回滚。升级脚本可以备份数据库(sdb_basebackupclone/backupcmd)。备份后的改变将丢失。[0487]自驾数据库(self‑drivingdatabase,sddb)接口[0488]可以在自驾数据库(sddb)框架上构建影子目录升级的生产首次展示。[0489]在每个状态转换中,工作流编制器都可以调用由升级团队实现的“函数”。[0490]这些函数可以在sddbrepo中的go软件包(package)中实现。可以将它们编译到sddb编制器中。这些函数可以调出必须与第二版本匹配的sdb二进制(诸如psql、pg_dump和pg_dumpall),以及标准的linux命令(cp、cat、awk和sed)。运行编制器的主机应该能够使用psql连接到数据库服务器。[0491]如果任何函数返回错误,则可以(在清理后)中止工作流。[0492]由于不应在当前python脚本和go软件包两者中维护下一代升级,因此编制器也可以在app开发人员环境中处理升级。开发人员环境中的升级可以与生产环境完全不同(容器与非容器、单节点与高可用性(ha)/灾难恢复(dr)等)。在配置中,可以构建单个编制器来处理这两种情况。在另一种配置中,可以创建另一个go二进制来处理app开发人员环境。影子目录的创建对于这两种途径可以是相同的。[0493]步骤详情[0494]更新步骤可以在两个位置逻辑地执行:(1)升级二进制/编制器和(2)升级控制器。自驾数据库控制器可以是经由grpc可访问的长期运行的过程。因此,编制器可以通过grpc与控制器进行通信。在短期内,控制器可以不在sdb映像中。对于为app开发人员设计的更新二进制,它可以与控制器代码一起编译为单个二进制。[0495]准入条件检查[0496]工作[0497]·检查数据库版本是否足够新以支持影子目录升级。[0498]·检查数据库版本是否比目标版本旧;如果是这样,则不允许降级。[0499]·检查源版本与目标版本之间是否没有释放壁垒。[0500]·检查数据库限制模式是否清除以防止并发升级。[0501]cmd:validatemaster[0502]作用器(actor):升级二进制/编制器;替代性地可以是主数据库的控制器[0503]步骤1:并行运行sdb_basebackup[0504]工作:如果需要支持sdb_basebackup,则更新postgresql.conf和pg_hba.conf。运行sdb_basebackup。[0505]作用器:升级二进制/编制器。[0506]步骤2:创建升级控制器[0507]升级控制器可以在容器中运行。自驾数据库编制器可以下载其docker映像并启动它。升级控制器需要一些不常见的配置参数(诸如禁用日志记录、二进制升级模式等)。配置文件是映像的一部分。[0508]app开发人员不使用容器。[0509]cmd:setupcontroller[0510]作用器:升级二进制/编制器[0511]步骤2.1:验证升级控制器[0512]占位符[0513]步骤3:禁用逻辑数据库创建[0514]工作[0515]·阻止dbddl[0516]cmd:blockdbddl[0517]作用器:升级控制器[0518]步骤4:从v1(主服务器)和v2(控制器)获取目录信息[0519]工作[0520]·获取pg_catalog、information_schema、检查器模式信息[0521]cmd:getcataloginfo[0522]作用器:升级控制器[0523]步骤5:启用数据库连接,暂停工作流[0524]工作[0525]·启用template0连接(主服务器和升级控制器两者)[0526]·暂停工作流(主服务器和升级控制器两者)[0527]cmd:enabledbconnectionsuspendworkflow[0528]作用器:升级控制器[0529]步骤6:创建影子目录模式[0530]工作[0531]·创建模式sdb_shadow_catalog和sdb_obsolete_catalogcmd:createshadowschemadef[0532]作用器:升级控制器[0533]步骤7:禁用ddl[0534]cmd:restrict_ddl[0535]作用器:升级控制器[0536]步骤8:创建影子目录数据[0537]工作[0538]·来自源的pg_dumpall模式[0539]·将psql加载到升级控制器中[0540]·从控制器复制到文件[0541]·从文件复制到源影子表[0542]·同步影子目录序列[0543]·如果pg_tenant改变形状,则转储并加载租户[0544]·更新影子模式内的relfilenode[0545]·生成影子relmapper文件[0546]cmd:createshadowschemadata[0547]作用器:升级控制器[0548]步骤9:停止升级控制器[0549]cmd:stopcontroller()[0550]作用器:升级二进制/编制器[0551]步骤10.a:重启主服务器(appdev)[0552]工作[0553]·清空[0554]·将新版本添加到存储设备目录·重命名影子relmapper文件[0555]·重启bkproxy[0556]·健全性检查第二版本[0557]cmd:rebootmaster[0558]作用器:升级二进制[0559]步骤10.b:关闭第一版本容器并启动第二版本容器[0560]作用器:编制器(需要重命名影子relmapper)[0561]步骤11:退出限制模式[0562]工作[0563]·清除数据库限制模式[0564]·禁用template0连接[0565]·(工作流暂停模式可能不是永久的)[0566]cmd:clear_restriction[0567]作用器:升级二进制/编制器[0568]步骤12:清理[0569]工作[0570]·删除旧目录[0571]·从存储设备目录中移除旧版本[0572]·关闭升级控制器[0573]cmd:clean_up[0574]作用器:升级二进制/编制器[0575]golang原型[0576]可以在sddrepo中构建golang版本,与数据库分开。二进制可以支持打印版本信息、从1.0.0开始的‑‑version标志。golang可以支持跨平台编译。构建脚本可以构建linux和osx二进制(例如,所有amd64)并且检入sdb源树。sdb构建脚本可以在其构建文件夹中挑选正确的二进制。[0577]sdd可以为每个ngupgrade版本进行分支。[0578]向后兼容日志重播[0579]当主服务器仍在第一版本上,而备用数据库已升级到第二版本时,所述备用数据库可以重播由第一版本二进制生成的日志。[0580]如果数据库备用实例检测到版本改变,则其相关要求可以是暂停日志重播。在高可用性(ha)中,可以先升级备用数据库。然而,灾难恢复(dr)实例可以独立于主数据库进行升级。如果在灾难恢复(dr)之前升级了主数据库,则灾难恢复(dr)会看到第二版本日志,它将不处理直到其已经升级。[0581]优化[0582]只要目录表不改变(模式和内置数据),就可能不需要创建影子表。这对于pg_tenant尤其重要。如果必要,可以使用相同的方式处理一些简单的表(诸如pg_workflow和pg_statistics)。[0583]升级推荐[0584]避免pgdata改变[0585]·relmapper文件[0586]·pg_control文件[0587]避免新的目录数据类型[0588]·可能需要分级[0589]避免pg_tenant改变[0590]·免除ddl锁定[0591]·升级无法阻止org注册[0592]
发明内容[0593]影子目录匹配第二版本二进制[0594]·很多指针(relfilenode)操作[0595]解决的问题:[0596]·无需额外的生产sku数据库服务器[0597]о使用在编制器节点上运行的轻巧数据库实例[0598]·减少升级灾难恢复(dr)的时间[0599]о在主位点中创建影子目录,并且将其复制到灾难恢复(dr)[0600]app开发[0601]在重启第二版本之前备份数据库[0602]直到重新启动第二版本的数据库时故障[0603]·只能与第二版本映像一起使用的影子目录[0604]·先前失败的运行中遗留的任何制品都可以在后续运行中清除在第二版本上重启数据库[0605]·关闭第一版本[0606]·升级第二版本relmapper文件[0607]·更新pg_version文件[0608]·更新postgresql.conf文件[0609]·在修改后的pgdata上弹出第二版本[0610]在重启过程之前,使用具有‑‑type=backup的sdb_basebackup备份第一版本[0611]sdb_basebackup[0612]·‑‑type=backup[0613]о通过tar流发生在pgdata下的文件、存储设备目录以及来自快照区[0614]о将文件从流中提取到备份pgdata中[0615]о用新的区id创建所有区[0616]о用新的cluuid创建新的存储设备目录,所述新的cluuid包含对重映射区id的引用[0617]·未来:‑‑type=clone[0618]·问题:在pgfilestore上,数据库不知道使用同一存储的其他实例[0619]·在ssd上,对于1gb数据和完整app模式–带有备份选项的sdb_basebackup耗时1.5分钟至2分钟[0620]测试[0621]·执行相同版本升级:[0622]о确保数据完整,可以执行ddl和dml[0623]о确保存储设备目录中的版本号和影子rel映射器文件已复制到灾难恢复(dr)[0624]·具有app运行的sdb.ngupgrade:[0625]о将ngupgrade作为工作量与chatter工作量同时运行[0626]о使用sfstore[0627]·具有ftests的sdb.ngupgrade:[0628]о在ngupgrade之前和之后运行ftest[0629]о当ngupgrade中发生错误时,检查第一版本数据库或第二版本数据库是否正在运行[0630]·sdb.ngupgrade_clean:[0631]о所有数据库限制模式均应关闭[0632]оtemplate0应该不允许访问[0633]·sdb.rollback_ngupgrade[0634]о回滚后,应运行数据库的先前版本[0635]о回滚后符号链接改变[0636]图17是展示了将数据库升级到第二版本的常规操作的实施例的图。[0637]图18是展示根据所公开的技术的将数据库升级到第二版本的操作的另一个实施例的图。[0638]图19是展示pg_class的实施例的图。[0639]图20是展示relmapper文件的实施例的图。[0640]图21是示出relfilenode的实施例的图。[0641]图22是展示根据所公开的技术的将数据库升级到第二版本的操作的又一实施例的图。[0642]图23是展示pg_catalog.pg_class中的样本数据的实施例的图。[0643]图24是展示根据所公开的技术的将数据库升级到第二版本的操作的仍另一个实施例的图。[0644]图25是展示在复制到影子目录之后pg_catalog.pg_class中的样本数据的实施例的图。[0645]图26是展示relfilenode互换的实施例的图。[0646]图27是展示影子目录升级的实施例的图。[0647]图28是展示高可用性(ha)升级的实施例的图。[0648]图29是展示灾难恢复(dr)升级的实施例的图。[0649]图30是展示管理符号链接的实施例的图。[0650]图31是展示刚好在重启之前管理符号链接的实施例的图。[0651]图32是展示重启之后管理符号链接的实施例的图。[0652]用于将数据库从第一版本升级到第二版本的各种实施方式可以包括计算机实施的进程和用于实践这些进程的装置或以计算机实施的进程和用于实践这些进程的装置的形式来实现。也可以以计算机程序产品的形式来实现实施方式,所述计算机程序产品具有包含以非暂时性和/或有形介质(诸如软磁盘、光盘只读存储器(cd‑rom)、硬盘驱动器、通用串行总线(usb)驱动器或任何其他机器可读存储介质),其中,当将计算机程序代码加载到计算机中并由其执行时,所述计算机成为用于实践用于将数据库从第一版本升级到第二版本的实施方式的装置。[0653]也可以以计算机程序代码的形式来实现实施方式,例如无论是存储在存储介质中、加载到计算机中和/或由计算机执行,还是通过某些传输介质(诸如通过电线或电缆、通过纤维光学器件)或经由电磁辐射传输,其中,当将计算机程序代码加载到计算机中并由其执行时,所述计算机成为用于实践用于将数据库从第一版本升级到第二版本的实施方式的装置。[0654]当在通用微处理器上实现时,计算机程序代码段将微处理器配置成创建特定的逻辑电路。在一些配置中,计算机可读存储介质上存储的计算机可读指令组可以由通用处理器实现,所述通用处理器可以将通用处理器或包含所述通用处理器的设备转换为被配置成实现或实行所述指令的专用设备。[0655]可以使用硬件来实现实施方式,所述硬件可以包括处理器(诸如通用微处理器)和/或应用专用集成电路(asic),所述asic在硬件和/或固件中实现根据所公开的主题的实现方式的全部技术或部分技术。处理器可以耦合到存储器(诸如随机存取存储器(ram)、只读存储器(rom)、闪存、硬盘或能够存储电子信息的任何其他设备)。存储器可以存储指令,所述指令被适配成用于由处理器执行以执行用于将数据库从第一版本升级到第二版本的技术。[0656]出于解释的目的,已经参考具体实现方式描述了上述描述。然而,上文的说明性讨论并不旨在是详尽的或将所公开的主题的实施方式限制于所公开的精确形式。鉴于以上教导,许多修改和变化是可能的。选择并描述实施方式以便解释所公开的主题的实施方式的原理及其实际应用,由此使得本领域的其他技术人员能够利用那些实施方式以及具有可能适合于预期的特定用途的各种修改的各种实施方式。当前第1页1 2 3 当前第1页1 2 3 
当前第1页1 2 3 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1