数据库升级与迁移实战
坑边闲话:最近正值双十一,关于淘宝超高并发的数据库大家可能都有所耳闻。数据库作为现代软件工业中最重要的技术,其蕴含的技术难度可谓是相当大。从关系型数据库的数学原理,到各种高级的数据结构,再到复杂的缓存优化,它们无不向 IT 从业者时刻展示这项技术的光辉与荣耀。本文创作于笔者给本地数据库进行升级、迁移的过程中,这或许并不是一个最佳实践,但我相信这篇文章肯定可以告诉你许多不为人知的数据库秘密。

1. 常见数据库·
1.1 PostgreSQL·
PostgreSQL 是一个开源、稳定且功能极其强大的关系型数据库,被誉为「世界上最先进的开源数据库」。它支持标准 SQL,同时提供丰富的扩展能力,例如 JSON、地理空间数据、全文检索和用户自定义函数。许多企业级产品,包括 GitLab、Mattermost、维基媒体后台,都在使用 PostgreSQL 作为核心数据库。它在可靠性、一致性和复杂查询优化方面表现突出,非常适合中大型业务系统以及对数据完整性要求极高的场景。
PostgreSQL 每年发布一个主版本(如 15、16、17),节奏固定且透明。每个主版本在发布后会提供 至少 5 年的官方维护支持,期间会持续提供安全补丁和稳定性修复,但不会引入破坏性变更。小版本更新(如 16.1 → 16.2)通常每季度发布一次,可直接升级且无需停库迁移。主版本升级需要 pg_upgrade 或数据迁移工具。这样的更新策略兼顾稳定性与创新,使 PostgreSQL 在企业级数据库中长期可靠。笔者建议在大多数情况下选择使用 PostgreSQL 即可。

很多人会疑惑:应用程序是否必须与 PostgreSQL 的版本严格匹配?例如,原本部署在 PostgreSQL 14 上的程序,是否可以直接换成 PostgreSQL 18 而不改应用代码?
在大多数情况下,答案是可以。
应用程序一般并不依赖 PostgreSQL 的内部实现,而是通过标准的 PostgreSQL 通信协议 进行交互(如 libpq、JDBC、Go 的 pgx 等驱动)。只要:
- 程序使用的 SQL 语法和特性没有在新版中删除或变更,
- 驱动版本支持所连接的 PostgreSQL 版本,
那么应用和数据库就不需要一一对应的版本绑定。也就是说,应用程序关心的不是 PostgreSQL 的版本号,而是 驱动和 SQL 功能是否兼容。
1.2 MariaDB·
MariaDB 是 MySQL 的一个社区驱动分支,由 MySQL 原始作者在 Oracle 收购 MySQL 后创建。它完全开源,遵循 GPL 许可证,在性能、稳定性和扩展性方面持续增强。MariaDB 保持与 MySQL 的高兼容性,绝大多数情况下可以直接替换使用,同时提供更多存储引擎(如 MyRocks、ColumnStore)以支持高并发和数据分析场景。凭借开放透明的社区治理模式和广泛的生态支持,MariaDB 已成为企业和自托管环境中常见的关系型数据库选择。
MariaDB 的更新通常遵循 半年一次主版本发布 的节奏(例如 10.6、10.7、10.11),新版本会带来性能优化、新存储引擎和兼容性改进。与 PostgreSQL 采用统一 5 年支持不同,MariaDB 的支持周期与版本性质有关:LTS(长期支持版本)提供约 5 年维护,普通版本维护约 1 年。小版本更新主要修复安全和稳定性问题,通常可直接升级。灵活的版本策略让用户可在“长期稳定”与“追求新特性”之间选择最合适的版本。

2. 笔者使用的容器服务·
2.1 Mattermost·
Mattermost 是一个开源的、可自托管的、类似 Slack 的团队沟通、协作软件。Mattermost 是笔者来到英国之后首先接触到的团队协作软件,它并不是一个社交软件,因为它的账户属于邀请制。根据官方描述,在容器化部署之前,首先要拉取容器化部署相关的仓库,并进行简单修改。
1 | git clone https://github.com/mattermost/docker |
该仓库提供了一个 env.example 文件,用户可以根据这个文件定制自己需要的运行时参数:
1 | DOMAIN=app-mattermost.littlenewton.cn |
2.1.1 现状分析·
此前笔者一直私有化部署并使用 Mattermost,最近偶尔看到 PostgreSQL 13 还有两三天就彻底 EOL,于是赶忙升级数据库。为了更好地面向未来,笔者决定直接从 pg13 直接升级到最新的 pg18.
下面简单介绍如何升级与更新。
pg13 的数据目录在 /var/lib/postgresql/data, 然而 pg18 要求使用 version-specific 目录 (/var/lib/postgresql/<major>/main),如 /var/lib/postgresql/18/main. 该目录由环境变量 PGDATA=/var/lib/postgresql/18/main 唯一确定。由此我们也也发现了容器化的问题:如果要在同一个容器里进行 pg_upgrade, 则
- pg13 需要挂载
/var/lib/postgresql/data, - pg18 要创建
/var/lib/postgresql/18,
两者的挂载路径产生交叠,容易引发非确定性的问题。为了避免更进一步的麻烦,笔者选择使用 pg_dump 和 pg_restore.
2.1.2 准备环境·
首先,原本的容器基于 postgres:13-alpine, 这个精简版系统安装软件包非常麻烦,为此我们先换为 postgres:13-trixie,然后仅启动 compose 中的 PostgreSQL 数据库。进入数据库之后首先将备份文件写入 /tmp 目录。一般情况下容器的 /tmp 目录和宿主机 /tmp 是一致的(-v 导入持久卷)。执行下列命令导出 Mattermost 数据库为文件。
1 | pg_dump mattermost -U mmuser --no-privileges > /tmp/postgres13-update-backup.sql |
随后,我们即可修改 Mattermost 的 compose 文件:
- 将
postgres:13-alpine标签改为postgres:18-trixie. - 另外,pg18 的挂载方式有了显著变化:应该将本地的
postgresql目录挂载到容器内的/var/lib/postgresql.
随后仅启动 Mattermost compose 的 PostgreSQL 服务:
1 | docker compose up -d postgres |
至此,数据库升级完毕!随后更改 Mattermost 版本标签,然后直接启动新版 Mattermost 即可!
2.2 PhotoPrism·
PhotoPrism, 成功升级 Mariadb 11.8 长期支持版,可以维持两三年时间。升级成功!
MariaDB 的升级貌似要更容易一些。
2.3 NextCloud·
NextCloud, 目前使用 MariaDB 10.6,长期支持版,但是好景不长,根据 https://endoflife.date/mariadb 说明,还有八个月的支持周期。因此在官方推出新版 docker compose 之前,保持现状是最稳妥的。
2.4 Harbor·
Harbor 使用了自己提供的特殊版本 PostgreSQL, 目前最新版为 pg15, 属于一个不新也不旧的版本。Harbor 的升级也能自动化处理,只要提供新版的 Docker Compose 脚本,Harbor 可以自动完成数据库升级。当然,Harbor 最麻烦的并不是数据库本身,而是它需要多级操作才能创建服务:
- 下载模板
- 编辑制导 yaml 文件
- 根据 yaml 文件生成 compose 文件
- 启动服务
由于 Harbor 依赖模板文件里的几个配置文件,因此需要在存储路径上做很多手动操作,比如拷贝配置文件到指定路径,已经修改文件权限为 0755 等。相比之下,数据库操作可谓是非常简单,直接交由 Harbor 自己处理即可。
2.5 Immich·
目前依赖 pg14, 同时依赖许多插件,因此官方提供了一个特殊版本的 pg14. 然而,Immich 服务在笔者的系统上已经无法使用,从外部图像库导入图片基本上全部失败,估计是软件有问题。Immich 升级还要留待明日。
总结·
此番数据库升级,让笔者重新审视了路径映射已经 ZFS 数据集命名规则以及 recordsize 设置的问题。总体来看收益还是很明显的。










