Featured image of post Firefish 数据库升级记录

Firefish 数据库升级记录

升级个数据库还怪麻烦的。

我的 Firefish 实例搭建于去年的 11 月,使用的数据库版本自然不是最新的,确切的说,是 PGroonga 12,一个基于 5 年前的 Postgres 的远古版本。为了避免今后的兼容性问题和安全问题,同时为了更好的性能,今天这数据库是非升级不可。

PostgreSQL 12 是在 2019 年发布的

升级一个用 Docker 跑起来的数据库和升级其他的 Docker 容器有很大不同,并不是拉取一个新的镜像就可以宣告结束。因为 Postgres 几乎每个大版本都有 Breaking Changes,新老版本产生的持久化文件并不兼容,如果直接拉取一个新的镜像运行,数据库是无法启动的,必须要采用一定的手段进行数据的迁移。

Postgres 有官方的升级工具pg_upgrade1,这一次我不采用,因为我的数据库跑了一年多,而且用的还是 5 年前的老版本,用这个工具我不确定会不会出问题。这次迁移,大致思路是先导出 SQL,再将导出的 SQL 导入新版本。

升级前的部署概况

以下是一些升级前需要了解的配置信息:

项目配置
实例部署方式Docker Compose
数据库容器名称firefish_db
升级前的数据库容器镜像groonga/pgroonga:3.1.9-alpine-12-slim
数据库用户example-firefish-user
数据库名称firefish

Docker Compose 的数据库部分如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
db:
    restart: unless-stopped
    image: groonga/pgroonga:3.1.9-alpine-12-slim
    container_name: firefish_db
    networks:
      - calcnet
    env_file:
      - .config/docker.env
    volumes:
      - ./db:/var/lib/postgresql/data
    healthcheck:
      test: pg_isready --user="$${POSTGRES_USER}" --dbname="$${POSTGRES_DB}"
      interval: 5s
      timeout: 5s
      retries: 5

导出当前数据库

对数据库进行升级之前,首先下线 Firefish 的编排:

1
docker compose down

单独启动数据库容器,导出当前数据库为 SQL:

1
2
docker compose up -d db
docker exec -it firefish_db pg_dumpall -U example-firefish-user > backup.sql

由于 Firefish 的数据库比较大,导出过程可能需要很长一段时间,比如我的个人实例就用了十几分钟。

导出文件的处理

可能是由于新版的 Postgres 认证方式有所变更,如果直接向新数据库导入之前导出的backup.sql文件,就会改变新数据库的 Authentication Scheme,导致之后 Firefish 连接数据库时认证失败。要避免这个问题需要对目前的backup.sql进行一些处理,只抽取出其中的firefish数据库的部分,而不是直接导入所有数据。2

1
2
3
#!/bin/bash
[ $# -lt 2 ] && { echo "Usage: $0 <postgresql dump> <dbname>"; exit 1; }
sed  "/connect.*$2/,\$!d" $1 | sed "/PostgreSQL database dump complete/,\$d"

编辑一个 Shell 脚本为以上内容,保存至script.sh,用以处理目前的backup.sql

1
2
3
nvim script.sh  # 或者任何你喜欢的编辑器
chmod +x script.sh
./script.sh backup.sql firefish >> upgrade.sql

如果一切顺利,当前目录下就会出现一个名为upgrade.sql的文件,可以打开它看一下,确保其被正确导出。

向新数据库导入现有数据

修改docker-compose.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
db:
    restart: unless-stopped
    image: groonga/pgroonga:3.2.2-alpine-16-slim  # 最新的容器
    container_name: firefish_db
    networks:
      - calcnet
    env_file:
      - .config/docker.env
    volumes:
      - ./database:/var/lib/postgresql/data # 注意这一行的变动
    healthcheck:
      test: pg_isready --user="$${POSTGRES_USER}" --dbname="$${POSTGRES_DB}"
      interval: 5s
      timeout: 5s
      retries: 5

注意数据库目录映射配置由./db:/var/lib/postgresql/data变为./database:/var/lib/postgresql/data,这么做是为了给新的数据库一个 Fresh Start,同时也保存老的持久化数据,即使出现问题,也可以随时用回老的数据库。

拉取并启动新容器:

1
2
docker compose pull
docker compose up db -d

向新数据库导入upgrade.sql

1
cat upgrade.sql | docker exec -i firefish_db psql -U example-firefish-user -d firefish

取决于数据库的大小,导入过程也会持续较长的时间。

收尾工作

导入完成,启动整个编排:

1
2
docker compose stop db
docker compose up

导入后的首次启动不建议带-d参数,建议不带参数启动,确保启动过程没有问题后再以-d参数启动。

最后,登入刚刚启动的 Firefish 实例,检查是否有任何数据损失,没有问题的话就大功告成啦🎉


  1. 官方文档:https://www.postgresql.org/docs/current/pgupgrade.html ↩︎

  2. 参考:https://thomasbandt.com/postgres-docker-major-version-upgrade ↩︎

Licensed under CC BY-NC-SA 4.0