PostgreSQL 16发布之后,我们第一时间在测试环境升级了。本以为就是个常规版本升级,没想到踩了不少坑。这里把经历过的问题整理出来,给打算升级的朋友做个参考。

升级的坑

第一个坑是升级前没做完整备份。说起来是低级错误,但当时觉得就是个小版本升级,应该不会出问题,就只做了逻辑备份。结果升级过程中出了意外,想回滚的时候发现物理备份没有,只能用逻辑备份恢复,多花了好几个小时。

第二个坑是直接在生产库上升级。第一次升级是在测试环境,一切顺利。于是就有点飘了,想直接在生产上操作。还好被同事拦住了,先在预发布环境跑了一遍,果然发现了兼容性问题。要是直接上生产,后果不堪设想。

第三个坑是没留够升级时间。我们的库不算特别大,但数据量也有几百个G。原以为升级半小时就能搞定,结果光数据迁移就花了两个多小时。后来才知道,大版本升级的时间和数据量强相关,不能凭感觉估。

现在我们的升级流程是:先做物理备份,在测试环境完整跑一遍,确认兼容性和性能,选在业务低峰期操作,预留足够的时间窗口,升级后观察至少一天。

性能的坑

升级之后最先遇到的性能问题是查询变慢。有几个平时很快的查询,升级之后突然慢了好几倍。查了半天,发现是统计信息没有更新,优化器选了不好的执行计划。跑了一遍ANALYZE之后就恢复正常了。

第二个性能问题是索引失效。有个查询原来走索引扫描,升级之后变成了全表扫描。仔细一看,是因为新版本的成本估算参数变了,原来的设置不再合适。调整了randompagecost之后,执行计划就正常了。

第三个问题是连接数打满。升级之后高峰期连接数经常到上限。查了一下,发现新版本的某些操作会持有连接更久,原来的连接数配置不够用了。调高了max_connections,同时加了连接池,问题才解决。

还有一个内存相关的坑。sharedbuffers按老经验设了内存的25%,但新版本在某些场景下对内存的使用模式变了,导致频繁的磁盘交换。后来根据实际负载调整了sharedbuffers和work_mem的比例,性能才稳定下来。

配置的坑

PostgreSQL的配置项很多,升级之后有些默认值变了,如果不注意就会踩坑。

workmem这个参数,新版本的默认值没变,但我们发现某些复杂查询在新版本里需要更大的workmem才能走哈希连接。设小了就会走磁盘排序,慢得不行。后来根据查询类型做了分级配置,复杂查询单独调大。

maintenanceworkmem也踩过坑。建索引的时候,这个值设小了会导致建索引特别慢。我们有个大表建索引,原来半小时能完成,升级之后跑了两个小时还没好。调大maintenanceworkmem之后,二十分钟就建完了。

WAL相关的配置也很重要。升级之后写操作变多了,原来的walbuffers和checkpoint配置不够用,导致频繁的checkpoint,磁盘IO飙升。调整了walbuffers、checkpointtimeout和maxwal_size之后,写入性能恢复正常。

我的建议是,不要直接沿用老版本的配置。升级之后在测试环境跑一遍典型负载,根据实际情况调整参数。PostgreSQL的官方文档里有每个版本的变更说明,一定要看。

兼容性的坑

驱动兼容性是最容易忽略的。我们用的是比较老版本的psycopg2,升级之后发现某些新特性用不了,还有几个查询报奇怪的错误。升级驱动之后就好了。

SQL语法方面,PostgreSQL 16对某些语法的检查更严格了。有几个历史遗留的SQL,在老版本能跑,新版本直接报错。都是一些不规范的写法,比如隐式类型转换、歧义的列名。虽然改起来麻烦,但也逼着我们把代码规范了一遍。

扩展兼容性也要注意。我们用了几个第三方扩展,升级之后发现其中一个还没有适配PostgreSQL 16,装不上。只能等作者更新,或者临时换替代方案。升级之前一定要检查所有依赖的扩展是否支持新版本。

应用框架层面,ORM的兼容性也可能出问题。我们用的ORM在新版本下有个查询生成的bug,导致生成的SQL有语法错误。升级ORM版本之后解决了。

运维的坑

备份恢复是运维的基本功,但升级之后一定要重新验证备份恢复流程。我们有一次升级后没测试恢复,后来需要恢复的时候才发现备份脚本有问题,差点出事。现在每次大版本升级之后,都会做一次完整的恢复演练。

监控也不能少。升级之后要重点关注慢查询、连接数、磁盘IO、复制延迟这些指标。新版本的行为可能和老版本不一样,原来的阈值可能需要调整。

VACUUM是PostgreSQL运维的老生常谈。升级之后我们发现autovacuum的触发频率变了,有几张大表膨胀得厉害。调整了autovacuum的参数,针对大表单独设置了更激进的策略,才控制住膨胀。

几点经验

第一,大版本升级一定要谨慎。先测试,再预发布,最后才上生产。每一步都要验证,不要跳步。

第二,备份是生命线。升级前必须有可验证的备份,而且要确认恢复流程可用。没有备份的升级就是赌博。

第三,不要迷信默认配置。每个版本的默认值都可能变,每个业务的负载特征也不一样,配置要根据实际情况调。

第四,监控要跟上。升级之后的观察期至少一周,有问题早发现早处理。

第五,持续学习。PostgreSQL每个版本都有新特性和变化,花时间看release notes和官方文档,比踩坑之后再补课强得多。

PostgreSQL 16是个很好的版本,性能和功能都有提升。只要升级前做足准备,升级后仔细观察,大部分坑都是可以避开的。