警告! 升级需要大量的空闲磁盘空间(数据库大小的 2 倍)。
我们刚刚完成了将 Docker 镜像升级至 PostgreSQL 18 的更改。任何通过命令行重建 Discourse 的网站管理员都将从之前的 PostgreSQL 15 升级至 PostgreSQL 18。请注意,如果您在 2025 年 PostgreSQL 15 更新 发布时 选择暂缓升级,您可以跳过该升级步骤,直接升级至 PostgreSQL 18。
如果您之前暂缓了升级,请将 app.yml 中的 PostgreSQL 模板从 templates/postgres.13.template.yml 更改为 templates/postgres.template.yml。
与任何升级一样,强烈建议在执行任何操作之前进行备份。
区域设置变更
过去,我们在 glibc 更新期间(例如操作系统升级时)曾遇到过索引损坏的问题。自 PostgreSQL 17 起,出现了一种新的 内置区域设置提供程序,它与操作系统的 glibc 解耦,因此跨版本更加稳定。作为此次升级的一部分,我们将迁移至使用 C.UTF-8 区域设置的内置提供程序。该区域设置使用代码点排序,出于上述稳定性原因,我们推荐使用它。
为了实现区域设置的变更,我们需要首先使用内置区域设置提供程序创建新的数据库集群,然后将数据库转储并恢复到该集群中。因此,与之前执行原地升级的情况相比,此次升级所需的磁盘空间更大。
更新
官方安装指南(单容器)
在下一次重建时,您将在末尾看到以下消息:
-------------------------------------------------------------------------------------
POSTGRES 升级完成
旧版 15 数据库存储在 /shared/postgres_data_old
要完成升级,请再次使用以下命令重建:
./launcher rebuild app
-------------------------------------------------------------------------------------
这意味着升级过程一切顺利!您只需执行一次新的重建,即可让您的网站恢复运行。
数据容器安装
如果您运行的是基于我们 discourse_docker 仓库中提供的示例的专用数据容器设置,请务必确保以安全且干净的方式关闭 PostgreSQL。
如今,我们有后台作业运行耗时数分钟的查询,因此关闭 Web 容器有助于数据容器安全关闭。
./launcher stop web_only
./launcher stop data
./launcher rebuild data
./launcher rebuild data
./launcher rebuild web_only
在对数据容器执行第一次重建之前,您可以查看 PostgreSQL 日志,以确认其是否已正确关闭。
如果关闭过程正常,运行 tail -f shared/standalone/log/var-log/postgres/current 应显示以下日志:
2025-01-24 09:19:06.437 UTC [37] LOG: received smart shutdown request
2025-01-24 09:19:06.444 UTC [37] LOG: background worker "logical replication launcher" (PID 54) exited with exit code 1
2025-01-24 09:19:06.446 UTC [49] LOG: shutting down
2025-01-24 09:19:06.468 UTC [37] LOG: database system is shut down
推迟更新
如果您需要在下次重建时推迟更新,可以通过将 app.yml 文件中的 PostgreSQL 模板从 "templates/postgres.template.yml" 更改为 "templates/postgres.15.template.yml" 来实现。
不建议这样做,因为一些网站管理员可能会忘记在之后恢复更改。
更新后的可选任务
优化 PostgreSQL 统计信息
更新后,新的 PostgreSQL 将没有现成的表统计信息。您可以使用以下命令生成这些统计信息:
docker exec -u postgres app \
/usr/lib/postgresql/18/bin/vacuumdb -d discourse --analyze-in-stages
清理旧数据
对于标准安装,您可以使用以下命令删除 PG15 格式的旧数据:
cd /var/discourse
./launcher cleanup
如果您有单独的数据容器,则需要像这样删除备份副本:
rm -fr /var/discourse/shared/data/postgres_data_old/
常见问题
源集群未正常关闭
如果出现上述消息导致升级失败,您可以尝试一种更简单的方法来使其恢复到更好的状态。
使用 ./launcher start app 重新启动旧容器。等待几分钟,直到其恢复运行。
现在再次使用 ./launcher stop app 将其关闭。之后查看日志,确认是否为正常关闭:
tail -f shared/standalone/log/var-log/postgres/current
2025-01-24 09:19:06.437 UTC [37] LOG: received smart shutdown request
2025-01-24 09:19:06.444 UTC [37] LOG: background worker "logical replication launcher" (PID 54) exited with exit code 1
2025-01-24 09:19:06.446 UTC [49] LOG: shutting down
2025-01-24 09:19:06.468 UTC [37] LOG: database system is shut down
如果日志未显示数据库已关闭,您可以再次启动旧容器,使用 ./launcher enter app 进入,运行以下命令,完成后再次查看日志。
export SVWAIT=300
sv stop nginx
sv stop unicorn
sv stop postgres
exit
如果日志与上述内容一致,现在您可以使用 ./launcher rebuild app 再次尝试升级。
数据库 “postgres” 的 lc_collate 值不匹配
如果您为数据库使用了非默认区域设置,则会出现此错误。据报道,需要设置 3 个变量才能成功。请确保您的 app.yml 文件中的 env: 部分包含以下 3 行:
LC_ALL: en_US.UTF-8
LANG: en_US.UTF-8
LANGUAGE: en_US.UTF-8
将 en_US.UTF-8 更改为您的区域设置。
每次重建都会再次执行升级(即升级循环)
发生这种情况时,您的升级日志中将包含以下内容:
mv: cannot move '/shared/postgres_data' to '/shared/postgres_data_old/postgres_data': Directory not empty
mv: cannot move '/shared/postgres_data_new' to '/shared/postgres_data/postgres_data_new': Directory not empty
这意味着上次升级的文件仍然残留。请在继续之前将这些文件移至其他位置。
我跳过了 PostgreSQL 15 更新,现在该怎么办?
您可以遵循本指南顶部的标准说明,它们将从您的版本顺利升级至 18,不会出现问题。