升级 PostgreSQL 到 16 版本(适用于 Policr Mini)
为什么要升级
在 Policr Mini 项目成立时 PostgreSQL 的大版本为 12
,而现在的 PostgreSQL 已进化到 16
版本。落后数个数据库大版本的状态对于项目的可持续发展是不利的,这便是升级原因。
注释
如果您的实例使用的数据库版本已经是 16
或更新的版本,您不需要做这些。官方实例于 2023-08-18
完成升级,部署于此日期之后的实例通常也不需要升级(因为文档的配置模板中的版本已是最新)。
一般的升级步骤
PostgreSQL 官方有一个叫做 pg_upgrade
的工具,它可以直接将旧版本的数据兼容性提升到新版本。但是这个工具有一些限制,比如不能跨大版本升级。
如果要将 12
版本升级到 16
版本,我们需要循序渐进的经历这期间的所有大版本的过渡升级:12
-> 13
-> 14
-> 15
-> 16
。这太过于繁琐,所以我们不使用这种方法。
提示
若我们后续会紧跟 PostgreSQL 的版本步伐,pg_upgrade
其实也可以是合适的工具。
数据备份与还原,升级一步到位
我们可以通过 pg_dump
和 pg_restore
两个工具来备份和还原数据,这样就可以一步到位的完成数据兼容性和数据库版本的升级。
具体步骤
以下步骤都默认在项目根目录下运行,也就是 docker-compose.yml
存在的目录。请先 cd
到该目录下,再往下看。
- 创建数据备份目录:
mkdir dumps
。此步骤是为了让数据备份文件可以存放到指定的宿主机(Host)目录中,为备份和还原做准备。 - 编辑
docker-compose.yml
文件,在services
->db
->volumes
下添加- ./dumps:/dumps
,请注意缩进的正确性。此步骤是为后续还原数据做准备。 - 停止机器人服务:
docker compose stop server
。此步骤是为了避免在备份和还原期间,机器人向数据库写入新的变化。 - 备份数据:
docker compose exec db pg_dump -U postgres -F c -Z 5 policr_mini_prod > dumps/policr_mini_prod.dump
。此步骤是向db
容器直接发起命令调用pg_dump
工具备份数据到dumps
目录。命令执行时间可能稍长,执行完毕后通过ls -lh dumps
命令查看备份文件的大小,通常不会太过巨大因为有经过压缩。 - 停止数据库服务:
docker compose stop db
。此步骤将数据库容器停止,非必要但最好这样做。 - 编辑
docker-compose.yaml
文件,在services
->db
->image
后面将postgres:12
修改为postgres:16
。然后执行docker compose up --no-start
命令更新镜像但不启动容器(避免无意义的启动)。此步骤先是将数据库版本修改为最新版,然后再拉取该版本镜像并应用到容器中。注意,此时我们还没有正式启动新的镜像。 - 备份原始数据目录:
mv _data _data.bak
。此步骤是将上一个版本的数据库的数据目录完整的备份起来,在启动新镜像后会生成新的_data
目录,不会造成对旧数据的干扰。 - 启动新的数据库:
docker compose start db
。此步骤是将新版本的db
容器启动,它会生成新的_data
目录,但其中空无一物(指机器人数据),为还原做准备。 - 还原数据:
docker compose exec db bash -c 'pg_restore -U postgres -d policr_mini_prod < /dumps/policr_mini_prod.dump'
。此步骤是向db
容器直接发起命令调用pg_restore
工具还原此前保存到宿主机dumps
目录中的备份文件。由于此前我们已经添加了新的volumes
配置,所以容器中读取的是/dumps
目录而不是./dumps
,在容器中前者映射到后者。注意,此命令可能需要相当长的时间才能执行完毕,最终在_data
目录生成的数据总大小也可能相当巨大(取决于数据量),在执行前请判断服务器磁盘空间是否足够。 - 最后,使用
docker compose up -d
命令重新部署并启动所有容器。
上述步骤虽然看起来很多,但原理非常简单,核心就是备份和还原两步而已。为了保证数据安全和正确性,本文档细心的添加了一些严格按照顺序停止部分容器和启动部分容器的步骤,以及详细的解释。
检查有效性
通过 docker compose logs
命令查看机器人容器和数据库容器的日志中是否出现致命错误,如 database files are incompatible with server
等。如果没有或者只是一些不致命的警告,通常表示已经成功。
警告
由于升级过程中机器人停止运作了一段时间,此期间的新请求被忽略或启动后短暂的异常现象是可能发生的。
结束语
如果你对此有充分的了解,也可以选择自己的效率更高的方式升级数据兼容性和数据库版本,但切记操作前要备份旧版本数据。
祝你们升级愉快,成功,顺利!