ВНИМАНИЕ! Если ваша база данных очень большая, вам потребуется много дополнительного дискового пространства (в 2 раза больше размера базы данных), и вы должны быть предельно осторожны при этом обновлении!
Мы только что внедрили изменения для обновления нашего Docker-образа до PostgreSQL 13. Любой администратор сайта, собирающий Discourse из командной строки, будет обновлен с предыдущей версии PostgreSQL 12 до PostgreSQL 13. Обратите внимание, что если вы откладывали обновление, когда выходило обновление PostgreSQL 12 еще в мае, вы можете пропустить это обновление и сразу перейти к PostgreSQL 13.
Если вы ранее откладывали обновление, измените шаблон PostgreSQL в app.yml с templates/postgres.10.template.yml на templates/postgres.template.yml.
Как и при любом обновлении, настоятельно рекомендуется сделать резервную копию перед выполнением любых действий.
Обновление
Официальное руководство по установке (один контейнер)
При следующей пересборке в конце вы увидите следующее сообщение:
-------------------------------------------------------------------------------------
ОБНОВЛЕНИЕ POSTGRES ЗАВЕРШЕНО
Старая база данных 12 сохранена в /shared/postgres_data_old
Чтобы завершить обновление, выполните повторную сборку с помощью команды:
./launcher rebuild app
-------------------------------------------------------------------------------------
Это означает, что обновление прошло успешно! Вам нужно просто выполнить новую пересборку, чтобы ваш сайт снова заработал.
Установка с использованием контейнера данных
Если вы работаете в среде с выделенным контейнером данных, основанным на образце, предоставленном в нашем репозитории discourse_docker, убедитесь, что вы корректно и безопасно останавливаете PostgreSQL.
В настоящее время у нас выполняются фоновые задания, выполняющие запросы длительностью в несколько минут, поэтому остановка веб-контейнера поможет контейнеру данных завершить работу безопасно.
./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/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, если это ваш случай)
По моим тестам, эта процедура требует менее 1x текущего размера базы данных в свободном пространстве.
Откладывание обновления
Если вам нужно отложить обновление при следующей пересборке, вы можете заменить шаблон PostgreSQL в файле app.yml, изменив "templates/postgres.template.yml" на "templates/postgres.12.template.yml".
Это не рекомендуется, так как некоторые администраторы сайтов могут забыть вернуть изменение обратно.
Дополнительные задачи после обновления
Оптимизация статистики 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
Если вы сможете проверить размер post_timings до и после REINDEX, это будет отличной статистикой для публикации здесь!
Вы можете использовать следующий запрос для проверки 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/
Часто задаваемые вопросы
Исходный кластер не был остановлен корректно
Если вы получили ошибку обновления с вышеуказанным сообщением, вы можете попробовать более простой подход, чтобы вернуть систему в лучшее состояние.
Перезапустите старый контейнер с помощью ./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.
Значения lc_collate для базы данных “postgres” не совпадают
Эта ошибка возникает, если вы используете нестандартные локали для вашей базы данных. Было сообщено, что для успешного завершения необходимы 3 переменные. Убедитесь, что в секции env: вашего файла app.yml есть следующие 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 без проблем.
Если вы следуете инструкциям для сред с ограниченным дисковым пространством, адаптируйте номера версий соответствующим образом.