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 ↩︎