暂无图片
暂无图片
2
暂无图片
暂无图片
暂无图片

高效升级PostgreSQL

文章转载自公众号:PostgreSQL学徒
作者:熊灿灿
前言
版本升级对于运维人员和开发人员来说,是经常打交道的一件事,除了引入新的功能和特性之外,另外一点,便是对已知的bug和安全漏洞进行修复。我们知道,PostgreSQL的版本迭代是很快的,三个月一个小版本,一年一个大版本,每个大版本几乎都有重磅特性,如v9.4 支持了jsonb,v9.6 支持了并行,v10 支持了逻辑复制和声明式分区、v11 支持了JIT、存储过程等等,除了这些,对于运维人员和DBA来说,还会引入很多管理特性,比如 v14 引入的idle_session_timeout,就再也不需要配合 pg_timeout 插件或者写一堆复杂的定时kill脚本了,也不用担忧被大量的空闲连接和没有经验的连接池配置将连接数打爆了。
所以数据库版本升级是一件十分重要的事,避免踩到已知的bug,导致业务的不稳定。如果想了解个多的新特性或者每个特性的详细信息,请参考官网:
https://www.postgresql.org/docs/current/static/release.html
每一个新特性在特定场景下,都会对数据库和应用程序的性能带来质的飞跃,都会极大的节省开发及运维人员的时间成本、人力成本,所以我们为什么不站在巨人的肩膀上前行呢?
EOL
PostgreSQL 社区成员每年只会同时维护5个主版本,也就是说每个数据库版本都是有生命周期的,也即EOL,End of life
所以从今年 2 月份开始,对于 9.5 以前的版本数据库不再进行维护,当然你依然可以在官网上下载 9.5 以前的版本使用,但是如果在使用过程中出现了bug,那么社区成员只会在维护的版本中修复,9.5 以前的版本不会进行任何修改,所以为了避免再次踩到低版本的bug,升级数据库还是很有必要的。
快速对比
前文提到了升级的必要性,但是可以看到,PostgreSQL的版本太多了,如何高效对比呢?比如我从远古版本 9.5 升级到最新的13,中间过了好几年,不用想肯定数不尽的issue list,当然一股脑升上去也没啥问题,毕竟新版本总是好用的多,但是对于我们运维人员来说,还是需要知其然,神器来了:
https://why-upgrade.depesz.com/show?from=9.4&to=9.6.6&keywords=
看看效果,假如我要从9.5 - > 13,直接一步到位,可以看到修复了1916个bug,太好用了!感谢Hubert Lubaczewski大师。
升级方式
数据库升级分为两种,一种是小版本迭代升级,另一种是主板本升级。PostgreSQL 版本号由主要版本和次要版本组成。例如,PostgreSQL 12.4 中的 12 是主要版本,4 是次要版本;PostgreSQL 10.0 之前的版本由 3 个数字组成,例如 9.6.19,其中 9.6 是主要版本,19 是次要版本。
Starting with PostgreSQL 10, a major version is indicated by increasing the first part of the version, e.g. 10 to 11. Before PostgreSQL 10, a major version was indicated by increasing either the first or second part of the version number, e.g. 9.5 to 9.6.
Minor releases are numbered by increasing the last part of the version number. Beginning with PostgreSQL 10, this is the second part of the version number, e.g. 10.0 to 10.1; for older versions this is the third part of the version number, e.g. 9.5.3 to 9.5.4.
小版本升级
小版本升级不会改变内部的存储格式,因此总是和大版本兼容。例如,PostgreSQL 12.4 和 PostgreSQL 12.0 以及后续的 PostgreSQL 12.x 兼容。对于这些兼容版本的升级非常简单,只需要关闭数据库服务,安装替换二进制的可执行文件,重新启动服务即可。
大版本升级
接下来,我们主要讨论 PostgreSQL 的跨版本升级问题,例如从 PostgreSQL 12.x 升级到 PostgreSQL 13.x。大版本的升级可能会修改内部数据的存储格式,因此需要执行额外的操作。比如PostgreSQL 10,将 log 改成了 wal ,主要是为了防止某些新手将 xlog、clog 认为是日志文件,误删了,如果还没有备份那么就GG了。

甚至PostgreSQL为了数据的安全性,高版本还不能直接使用低版本创建的数据目录,会在日志中打印相关的错误信息。
官方提供三种大版本升级方案
  1. Upgrading Data via pg_dumpall,使用 pg_dumpall pg_restore 进行升级

  2. Upgrading Data via pg_upgrade,使用 pg_upgrade 进行升级

  3. Upgrading Data via Replication,使用逻辑复制进行升级

当然,还可以进行一下引申:
  1. pg_dump

  2. pg_dumpall

  3. pg_dumpall + pg_dump组合拳

  4. pg_upgrade

  5. 大于PostgreSQL 10: Logical replication

  6. 小于PostgreSQL 10: pglogical, Slony, Londiste, and Bucardo.

pg_dump
首先是最原始的pg_dump的方式,可以使用unix pipe,也可以使用-j 并行的方式,不过得配合pg_restore,需要额外去备份一些全局的信息如用户和表空间等。
目标库准备工作一切就绪之后,然后使用 pg_dump并行导出,或者直接一个管道的方式,这样可以进一步减少停机的时间。
sudo -u postgres pg_dump -h /path/to/old/instance.sock | sudo -u postgres psql -h /path/to/new/instance.sock
复制
pg_dumpall
pg_dumpall 的优势在于,可以导出全局的对象,如用户、表空间、全局的一些权限信息等等,所以相较于pg_dump就不需要导出用户信息等全局信息这一步骤了,不过不支持 -j并行,和pg_dump的步骤十分类似。
pg_upgrade
pg_upgrade是官方提供的一个升级工具,执行升级之前,需要使用 -c 或者 --check选项,进行升级前的兼容性检查, 可以发现插件、数据类型不兼容等问题。不过需要注意的是,源端和目标端的编译参数、segsize、walsegsize等等得是一样的,可以使用pg_config查看源端的编译参数
[postgres@xiongcc ~]$ pg_config | egrep 'CONFIGURE|CC'CONFIGURE =  '--prefix=/usr/pgsql-13' '--enable-debug' '--enable-cassert' '--enable-depend' 'CFLAGS=-O0 -ggdb' '--with-readline'CC = gcc -std=gnu99
复制
兼容性检测结果,类似如下:
常见的兼容错误如下:
  1. Upgrade Error - There seems to be a postmaster servicing the cluster,服务还在运行中,所以这也算是pg_upgrade的一个小小缺点,需要停机

  2. Upgrade Error - fe_sendauth: no password supplied,这个就简单处理,密码错误,指定pg_hba.conf或者.pgpass

  3. Upgrade Error - New cluster is not empty; exiting,需要保证目标库的data目录是空的

  4. Upgrade Error - Failed to load library,这个是最常见的,源端有一些第三方插件,而目标端没有,这个需要自己安装好对应的.so动态库即可

老样子,先将配置文件配置好,直接 cp 源端的即可,然后就可以升级了
对于pg_upgrade,提供了两种方式,一个是指定--link的方式,这样的话新版本数据库可以直接使用原有的数据库文件而不需要执行复制,通常可以在几分钟内完成升级操作,接近于 0 停机时间。不过值得注意的是,源端和目标端的编码一定要保持一致,不然就会失败。Note that pg_upgrade is only going to work in case the encodings of the old and the new database instance match. Otherwise, it will fail.
这里,还有一个隐含的concern:既然是link模式,所以前提是PostgreSQL去做链接的操作是可以成功的,不然当然也不可行,比如不能跨文件系统(即分区)进行创建。
不过link模式看似美好,实则不然,假如我以link的模式升级升上去了,我又因各种原因要回退,这里就复杂了
  • If the --check option was used, the old cluster was unmodified; it can be restarted.

  • If the --link option was not used, the old cluster was unmodified; it can be restarted.

  • If the --link option was used, the data files might be shared between the old and new cluster:

  • If pg_upgrade aborted before linking started, the old cluster was unmodified; it can be restarted.

  • If you did not start the new cluster, the old cluster was unmodified except that, when linking started, a .old suffix was appended to $PGDATA/global/pg_control. To reuse the old cluster, remove the .old suffix from $PGDATA/global/pg_control; you can then restart the old cluster.

  • If you did start the new cluster, it has written to shared files and it is unsafe to use the old cluster. The old cluster will need to be restored from backup in this case.

  1. 如果只运行了 --check 选项命令,表示没有真正执行升级,重新启动服务即可;

  2. 如果升级时没有使用 --link 选项,旧版本的数据库集群没有任何修改,重新启动服务即可;

  3. 如果升级时使用了 --link 选项,数据库文件可能已经被新版本的集群使用:

  • 如果 pg_upgrade 在链接操作之前终止,旧版本的数据库集群没有任何修改,重新启动服务即可;

  • 如果没有启动过新版本的后台服务,旧版本的数据库集群没有修改,但是链接过程已经将 $PGDATA/global/pg_control 文件重命名为 $PGDATA/global/pg_control.old;此时需要将该文件名中的 .old 后缀去掉,然后重新启动服务即可;

  • 如果已经启动了新版本的数据库集群,已经修改了数据库文件,再启动旧版本的服务可能导致数据损坏;此时需要通过备份文件还原旧版本的数据库。

另外一个模式就是不指定link了,这样就是硬生生的拷贝数据文件了,具体的速度取决于你的源端数据库大小。对于含有replica的数据库,可以使用rsync的方式进行升级,具体参照官网:https://www.postgresql.org/docs/current/pgupgrade.html
测试一下升级速度,大概花了10s
pg_upgrade 升级之后,不会生成新版本数据库的统计信息,但是会创建一个脚本文件,执行该文件:./analyze_new_cluster.sh,可以看到,最开始会收集一个最基本的统计信息,确保数据库可用,然后再收集一次更加全面的统计信息,分阶段的,另外假如修改了default_statistics_target,可以直接使用 "/usr/local/bin/vacuumdb" --all --analyze-only,因为升级过程目前不会复制数据分布的任何统计数据,比如像直方图、最常见的值及其频率之类的东西,所以这也是“vacuumdb –analyze-only –analyze-in-stage”的重要性,不然复杂查询的性能会受到相当大的影响
可以看到1 target、10 targets,分阶段来做的,可以使用SQL检测修改了target的表:
如果确认升级成功,可以选择删除或者保留旧的数据库软件和集群。pg_upgrade 同样提供了一个删除旧数据库集群的脚本:./delete_old_cluster.sh
rm –rf $OLDPGDATA
复制
升级之后,记得检查一下插件,必要时候可以执行update
alter extension xxx update;
复制
logical replication
PostgreSQL 逻辑复制支持跨版本之间的数据复制,而且支持不同平台之间的复制,因此也可以用于实现版本升级。我们可以安装一个新版本的数据库作为复制的从节点,当数据已经同步时执行一次主从切换,然后关闭旧版本的主节点。主从切换的升级方法通常只需要几秒钟就能完成,利用第三方高可用组件甚至可以实现零停机时间升级。
这个就不再演示了,可以参照之前的文章 《关于逻辑复制的方方面面》,可以使用原生的逻辑复制,也可以使用第三方扩展,如pglogical, Slony, Londiste, and Bucardo等等。也可以参照percona的例子:
  1. Continuous Replication From a Legacy PostgreSQL Version to a Newer Version Using Slony

  2. PostgreSQL Upgrade Using pg_dump/pg_restore

  3. Replication Between PostgreSQL Versions Using Logical Replication

  4. PostgreSQL Upgrade Using pg_dumpall

关于pglogical,相信也是最普遍的,使用pglogical进行升级的话,需要注意几个点,https://tech.coffeemeetsbagel.com/our-journey-to-postgresql-12-3d6ee15d305a
  1. Slow synchronization can be dangerous,针对订阅端进行优化,加速订阅

  • 删除需要同步的表上的所有索引

  • 关闭 fsync

  • 将 max_wal_size 设为 50GB

  • 将 checkpoint_timeout 设为 1h

  1. Every update is logged as a conflict

当 pglologic 断定发生了冲突时,它会发出一条日志消息,比如“CONFLICT: remote UPDATE on relation PUBLIC.foo. Resolution: apply_remote”。然而,我们观察到,订阅方处理的每个更新都会被记录为冲突。仅经过几个小时的复制,订阅方数据库就已经写入了 1GB 的冲突日志。设置pglogical.conflict_log_level = DEBUG 将其关闭,
对比
  • dump/dumpall + restore/psql:由于dump+restore总体相对耗时较长,因此不适用于大数据量的数据库,或是写入比较频繁的场景使用。尤其是对于核心的业务程序(特别是有99.999保证的程序)来说是不可接受的,好处就是十分安全,当然也可以不停机,使用逻辑复制搭配decoder_raw等Plugins解析出备份之后的操作SQL,不过不能保证一致性。

  • pg_upgrade:此方案优势是速度非常快,搭配并行和link模式,pg_upgrade –link –jobs xxx,但是必须停机升级,并且link模式,会无法使用以前的版本,因此不适用于7x24的场景,若使用默认模式,就地升级会导致磁盘使用率增倍,好处就是源端还可以用,同时假如还有standby或者流复制的场景下,可能还会丢失备库,可以使用官方推荐的rsync模式。同时值得注意的是,升级过程目前不会复制数据分布的任何统计数据,比如像直方图、最常见的值及其频率之类的东西,所以这也是“vacuumdb –analyze-only –analyze-in-stage”的重要性,不然复杂查询的性能会受到相当大的影响,还有就是make 、configure编译的参数得保持一致

  • 逻辑复制:此方案是最平滑的方案,比较适用于7x24小时以及大数据量场景,停机时间非常短,只有几秒钟,同时源端和目标端升级之后假如有需求,还是可以使用的。但是配置繁琐,尤其是v10以前的版本,还没有原生逻辑复制,需要第三方扩展,第三方扩展除了问题还是黑盒,增加了运维成本,同时还要有集群环境,但是原生逻辑复制又不支持序列、DDL(搭配插件pg_ddl_deploy,不过又回到了黑盒来了)、视图等等。

小结
可以看到,升级的方案还是很多的,合理选择适合自己的才是最好的。
参考
https://www.cybertec-postgresql.com/en/a-primer-on-postgresql-upgrade-methods/
https://blog.crunchydata.com/blog/performing-a-major-postgresql-upgrade-with-pg_dumpall
https://tech.coffeemeetsbagel.com/our-journey-to-postgresql-12-3d6ee15d305a
https://www.percona.com/blog/2019/04/12/fast-upgrade-of-legacy-postgresql-with-minimum-downtime-using-pg_upgrade/
https://www.endpoint.com/blog/2015/07/01/how-fast-is-pgupgrade-anyway
https://www.pgday.ch/common/slides/2017_T-DBI-20170630-001-PGDAY-Upgrade-BestPractices.pdf
https://www.cybertec-postgresql.com/en/upgrading-and-updating-postgresql/
https://www.postgresql.org/docs/current/pgupgrade.html
https://why-upgrade.depesz.com/show?from=13.1&to=13.3&keywords=

规模空前,再创历史 | 2020 PG亚洲大会圆满结束
PG ACE计划的正式发布
三期PostgreSQL国际线上沙龙活动的举办
六期PostgreSQL国内线上沙龙活动的举办

中国PostgreSQL分会与腾讯云战略合作协议签订

PostgreSQL 13.0 正式版发布通告

深度报告:开源协议那些事儿

从“非主流”到“潮流”,开源早已值得拥有

Oracle中国正在进行新一轮裁员,传 N+6 补偿

PostgreSQL与MySQL版权比较

新闻|Babelfish使PostgreSQL直接兼容SQL Server应用程序

四年三冠,PostgreSQL再度荣获“年度数据库”

更多新闻资讯行业动态技术热点,请关注中国PostgreSQL分会官方网站

https://www.postgresqlchina.com

中国PostgreSQL分会生态产品

https://www.pgfans.cn

中国PostgreSQL分会资源下载站

https://www.postgreshub.cn


点击此处阅读原文

↓↓↓

文章转载自开源软件联盟PostgreSQL分会,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论