警告! 如果您的数据库非常大,您将需要大量的额外磁盘空间(数据库大小的 2 倍),并且在进行此升级时应格外小心!
我们刚刚完成了期待已久的 PostgreSQL 主版本升级。任何通过命令行重新构建 Discourse 的站点管理员都将从旧的 PostgreSQL 10 升级到 PostgreSQL 12。
我们已在 Meta 上运行此新版本一段时间,一切正常。PostgreSQL 12 带来了许多改进,Discourse 将自动利用这些改进。
更新
官方安装指南(单容器)
在下次重新构建时,您将在末尾看到以下消息:
升级完成
----------------
要完成升级,请使用以下命令再次重新构建:
./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/data/log/var-log/postgres/current 如果关闭干净,应该会显示以下日志:
2020-05-13 18:33:33.457 UTC [36] LOG: received smart shutdown request
2020-05-13 18:33:33.464 UTC [36] LOG: worker process: logical replication launcher (PID 52) exited with exit code 1
2020-05-13 18:33:33.465 UTC [47] LOG: shutting down
2020-05-13 18:33:33.479 UTC [36] LOG: database system is shut down
手动更新 / 空间受限环境
在尝试此操作之前,您必须备份 POSTGRES_DATA
如果您处于空间受限的环境且无法获取更多空间,可以尝试以下方法:
./launcher stop app #(或者如果您的情况是,则同时停止 web_only 和 data)
mkdir -p /var/discourse/shared/standalone/postgres_data_new
docker run --rm \
-v /var/discourse/shared/standalone/postgres_data:/var/lib/postgresql/10/data \
-v /var/discourse/shared/standalone/postgres_data_new:/var/lib/postgresql/12/data \
tianon/postgres-upgrade:10-to-12
mv /var/discourse/shared/standalone/postgres_data /var/discourse/shared/standalone/postgres_data_old
mv /var/discourse/shared/standalone/postgres_data_new /var/discourse/shared/standalone/postgres_data
./launcher rebuild app #(或者如果您的情况是,先重建 data 再重建 web_only)
在我的测试中,此过程所需的空闲空间小于当前数据库大小的 1 倍。
推迟更新
如果您需要在下次重新构建时推迟更新,可以通过将 app.yml 文件中的 \"templates/postgres.template.yml\" 更改为 \"templates/postgres.10.template.yml\" 来交换 PostgreSQL 模板。
这不推荐,因为一些站点管理员可能会忘记之后还原此更改。
更新后的可选任务
优化 PostgreSQL 统计信息
更新后,新的 PostgreSQL 将没有现成的表统计信息。您可以使用以下命令生成这些统计信息:
cd /var/discourse
./launcher enter app
su postgres
psql
\connect discourse
VACUUM VERBOSE ANALYZE;
\q
exit
exit
或者上述命令的单行版本:
/var/discourse/launcher run app "echo 'vacuum verbose analyze;' | su postgres -c 'psql discourse'"
清理旧数据
对于标准安装,您可以使用以下命令删除 PG10 格式的旧数据:
cd /var/discourse
./launcher cleanup
如果您有独立的数据容器,则需要像这样删除备份副本:
rm -fr /var/discourse/shared/data/postgres_data_old/
常见问题解答 (FAQ)
源集群未干净关闭
如果您收到上述消息导致升级失败,可以尝试一种更简单的方法使其恢复到更好的状态。
使用 ./launcher start app 重新启动旧容器。等待几分钟直到它重新启动。
现在再次使用 ./launcher stop app 关闭它。之后查看日志以确认是否为干净关闭:
tail -f shared/data/log/var-log/postgres/current
2020-05-13 18:33:33.457 UTC [36] LOG: received smart shutdown request
2020-05-13 18:33:33.464 UTC [36] LOG: worker process: logical replication launcher (PID 52) exited with exit code 1
2020-05-13 18:33:33.465 UTC [47] LOG: shutting down
2020-05-13 18:33:33.479 UTC [36] LOG: database system is shut down
如果日志如上所示,现在可以使用 ./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
这意味着上次升级留下的文件仍然存在。在继续之前,请将它们移动到其他位置。