PostgreSQL 13 更新

:warning: 警告! 如果您的数据库非常大,您将需要大量的额外磁盘空间(数据库大小的 2 倍),并且对此升级务必格外小心!

我们刚刚完成了将 Docker 镜像升级至 PostgreSQL 13 的更改。任何通过命令行重新构建 Discourse 的网站管理员都将从之前的 PostgreSQL 12 升级到 PostgreSQL 13。请注意,如果您在 5 月份 PostgreSQL 12 更新 时选择暂缓升级,您可以跳过该步骤,直接升级到 PostgreSQL 13。

如果您之前暂缓了升级,请将 app.yml 中的 PostgreSQL 模板从 templates/postgres.10.template.yml 更改为 templates/postgres.template.yml

与任何升级一样,在执行任何操作之前,强烈建议进行备份。

更新

官方安装指南(单容器)

在下一次重新构建时,您将在末尾看到以下消息:

-------------------------------------------------------------------------------------
POSTGRES 升级完成

旧的 12 数据库存储在 /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/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

手动更新 / 空间受限环境

:warning::warning::warning:
在尝试此操作之前,您必须备份 POSTGRES_DATA
:warning::warning::warning:

如果您处于空间受限且无法获取更多空间的环境中,可以尝试以下方法:

./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/12/data \
	-v /var/discourse/shared/standalone/postgres_data_new:/var/lib/postgresql/13/data \
	tianon/postgres-upgrade:12-to-13
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.12.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'"

重建索引

此升级的主要功能是在每个实例中为最大的表 post_timings 及其索引节省大量空间。在完成成功的更新后,您需要运行一个命令来重建索引并享受其带来的好处。

cd /var/discourse
./launcher enter app
su postgres
psql
\connect discourse
REINDEX SCHEMA CONCURRENTLY public;
\q
exit
exit

如果您能在 REINDEX 前后检查 post_timings 的大小,那将是一个值得分享的有趣统计数据!

您可以使用以下查询来检查前 20 个最大的数据对象,分别在重建索引之前和之后运行:

WITH RECURSIVE pg_inherit(inhrelid, inhparent) AS
    (select inhrelid, inhparent
    FROM pg_inherits
    UNION
    SELECT child.inhrelid, parent.inhparent
    FROM pg_inherit child, pg_inherits parent
    WHERE child.inhparent = parent.inhrelid),
pg_inherit_short AS (SELECT * FROM pg_inherit WHERE inhparent NOT IN (SELECT inhrelid FROM pg_inherit))
SELECT table_schema
    , TABLE_NAME
    , row_estimate
    , pg_size_pretty(total_bytes) AS total
    , pg_size_pretty(index_bytes) AS INDEX
    , pg_size_pretty(toast_bytes) AS toast
    , pg_size_pretty(table_bytes) AS TABLE
  FROM (
    SELECT *, total_bytes-index_bytes-COALESCE(toast_bytes,0) AS table_bytes
    FROM (
         SELECT c.oid
              , nspname AS table_schema
              , relname AS TABLE_NAME
              , SUM(c.reltuples) OVER (partition BY parent) AS row_estimate
              , SUM(pg_total_relation_size(c.oid)) OVER (partition BY parent) AS total_bytes
              , SUM(pg_indexes_size(c.oid)) OVER (partition BY parent) AS index_bytes
              , SUM(pg_total_relation_size(reltoastrelid)) OVER (partition BY parent) AS toast_bytes
              , parent
          FROM (
                SELECT pg_class.oid
                    , reltuples
                    , relname
                    , relnamespace
                    , pg_class.reltoastrelid
                    , COALESCE(inhparent, pg_class.oid) parent
                FROM pg_class
                    LEFT JOIN pg_inherit_short ON inhrelid = oid
                WHERE relkind IN ('r', 'p')
             ) c
             LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
  ) a
  WHERE oid = parent
) a
ORDER BY total_bytes DESC LIMIT 20;

清理旧数据

对于标准安装,您可以使用以下命令删除 PG12 格式的旧数据:

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 值不匹配

如果您使用非默认区域设置(locales)作为数据库,会出现此错误。据报道,需要 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

这意味着上次升级留下的文件仍然存在。在继续之前,请将它们移动到其他位置。

升级完成建议脚本 - 我需要做什么吗?

一旦升级完成,您将看到 pg_upgrade 消息的输出如下:

Upgrade Complete
----------------
Optimizer statistics are not transferred by pg_upgrade so,
once you start the new server, consider running:
    ./analyze_new_cluster.sh

Running this script will delete the old cluster's data files:
    ./delete_old_cluster.sh

您可以安全地忽略此消息。

我跳过了 PostgreSQL 12 更新,现在该怎么办?

您可以遵循本指南顶部的标准说明,它们将无问题地将您的版本升级到 13。

如果您遵循空间受限环境的说明,请相应地调整版本号。

38 个赞
PostgreSQL Details
Discourse 2.7.0.beta2 Release Notes
Forum offline due to failed rebuilds on Tests-Pass
Nginx upstream timed out (110: Connection timed out)
Firewall issue with running multiple containers after upgrade
Help! Problem with firewall/permissions and postgre?
PostgreSQL 13 update from PostgreSQL 10 fails
PostgreSQL 13 update from PostgreSQL 10 fails
Unrecognized error type (ActiveRecord::StatementInvalid: PG::ProgramLimitExceeded
Recover from filesystem backup: can't rebuild nor start
Rebuild error: Errno::ENOENT: No such file or directory @ rb_sysopen - /e tc/postgresql/13/main/pg_hba.conf
Discourse broken after upgrade
Upgrade Failed from 2.7.0.beta1 to 2.7.0.beta3
Invalid location error after update
Upgrade failed!
Upgrade failed: PostgreSQL version 13 ... not compatible with ... version 10.12
Improved Bookmarks with Reminders
Importing old database to latest version
Errors encountered when uploading images
What else do I need to take care of when self hosting?
Rebuild freezing when attempting to stop container
Backup failed due to PG/SQL errors
Restore Failing - Check Free Disk Space
Supported postgresql versions
Wrong Error Message for too short replies for Reply-by-Email
Upgrade Postgres with REALLY limited space
Upgrade Postgres with REALLY limited space
Postgres has 100% CPU for large databases, Discourse 2.7.7
Upgrade failing with FAILED TO BOOTSTRAP
Stuck in an update loop after PostgreSQL 13 update
Problem with rebuild Discourse at Docker
After Rebuild got error: postgres:10/main, Causes CPU to go high
Call AdminDashboardGeneralData.refresh_stats at boot?
ERROR: You are running an old version of the Discourse image
Failed to upgrade to v2.9.0beta3
Failed to upgrade to v2.9.0beta3
SMTP Settings in app.yml reset?
Upgrade container - keeping config and data
Site down after failed update: permission denied to create extension "unaccent"
Rebuild fails on db:migrate w/PG12
Update from 2.9.0 beta2 to beta4 failed (my site is down)
Performance optimisation tips
Upgrading from 2.4 to 2.9. Need slight assistance on what order to run the final commands & reboot in
Problem when updating Discourse Forum
Troubleshooting severe performance issues with latest Discourse?
Slow Profile Loads with 100GB+ database
Use Nginx Proxy Manager to manage multiple sites with Discourse
Horizontal loading slider
Upgrading Discourse from 2.6.0.beta2
PostgreSQL 15 update
Got a lot of "Failed to backfill 'Reader' badge" errors
Trouble updating discourse after some time - UPGRADE OF POSTGRES FAILED
Database size/maintenance
Upgrade gone sideways [deprecated Guest Gate plugin]
Upgrade Issues: Failed Upgrade due to Duplicate Key, Failed Snapshot Restore
2.7.0.beta2 upgrade failed with ERROR: duplicate key
Problem, rebuild to latest version
Urgent, upgraded build failed UniqueViolation