
В данной статье описывается процесс мажорного обновления СУБД Greengage (open-source форк Greenplum) с помощью утилит pg_upgrade и ggupgrade. Утилиты находятся на этапе финальных доработок, тестирования и отладки на момент выхода статьи. Все дальнейшее описание и примеры актуальны для перехода Greengage с версии 6 на 7.
Введение
Современные приложения, которым требуется хранение и доступ к данным, немыслимы без надежной и производительной системы управления базами данных (СУБД). Обновление СУБД, как и любого другого ПО, является очень важным процессом. Есть множество причин, по которым нужно обновлять СУБД, и направлены они на улучшение стабильности, безопасности и эффективности вашей инфраструктуры.
Вот основные причины обновления СУБД:
Повышение безопасности.
Рост производительности.
Новые функциональные возможности.
Актуальность и поддержка сообщества. Оставаясь на актуальных версиях, можно получать полноценную поддержку от сообщества и разработчиков.
Более подробно с изменениями в новых версиях Greengage можно ознакомиться на странице Релизы.
Обновление СУБД можно разделить на два типа: минорное и мажорное. Минорное обновление версии СУБД PostgreSQL и Greengage (например, с версии 6.29 до 6.30) предполагает, что формат хранения данных не будет меняться, и поэтому достаточно обновить бинарные файлы СУБД. Мажорное обновление версии (например, с версии 6.29 до 7.4) может менять структуру системных объектов, поэтому здесь недостаточно обновить бинарные файлы — необходимо выполнить миграцию (перенос) данных в кластер следующей мажорной версии.
Миграцию данных выполняют с помощью логического бэкапа, что занимает достаточно много времени. В процессе создания логического бэкапа кластер должен быть неактивен для записи, а во время восстановления — полностью остановлен, если мы восстанавливаем на той же инфраструктуре. В производственных средах вопрос минимизации простоя БД стоит особенно остро. Для баз данных размером сотни терабайт и более, как для Greengage, это может означать часы или даже дни простоя, что неприемлемо для критически важных бизнес-процессов.
Обновление PostgreSQL с помощью утилиты pg_upgrade
Кластер Greengage — это распределенный кластер, состоящий из десятков или сотен инстансов, основанных на PostgreSQL. Более подробно ознакомиться с архитектурой Greengage можно в документации. Поэтому сначала рассмотрим утилиту pg_upgrade для обновления PostgreSQL, так как именно она взята за основу обновления кластера Greengage.
Идея pg_upgrade заключается в том, что в мажорных версиях меняется в основном структура системного каталога, а само физическое хранение данных — нет, за некоторыми исключениями, речь о которых пойдет ниже. Поэтому утилита генерирует команды создания объектов (БД, схемы, таблицы, функции и т.д.) и выполняет их на новом сервере, а затем копирует файлы данных.
Новые объекты должны иметь те же идентификаторы, что и на исходном кластере. Связано это в основном с тем, что в данных хранятся ссылки на TOAST-таблицы, то есть содержатся oid TOAST-таблиц. Изменить oid существующего объекта нельзя. Перед созданием каждого объекта pg_upgrade вызывает функцию, которая запоминает нужный oid, а затем это сохраненное значение используется при создании объекта. Таким образом, все пользовательские объекты имеют те же идентификаторы на новом кластере, что и на обновляемом кластере.
Далее выполняется копирование файлов данных сгенерированных объектов на новый кластер. Если заменить копирование файлов данных на создание жестких ссылок (включается параметром --link в pg_upgrade), то процесс обновления будет быстрее, чем в режиме копирования файлов данных. В режиме создания жестких ссылок pg_upgrade файлы данных исходного кластера не копируются, а создаются жесткие ссылки на них в обновляемом кластере. Файлы данных старого кластера можно будет в дальнейшем удалять, это не повлияет на данные целевого кластера. Ограничение составляет только изменение данных на старом кластере, так как в этом случае будет изменяться один и тот же файл, который используется в новом кластере. В случае использования жестких ссылок использовать одновременно исходный и целевой кластер нельзя, иначе будут изменяться одни и те же данные.
Для пользователя схема обновления PostgreSQL с помощью pg_upgrade выглядит следующим образом:
Установка новой версии PostgreSQL на кластере, который нужно обновить.
Инициализация кластера новой версии.
Запуск утилиты
pg_upgradeс указанными директориями бинарных файлов и файлов данных для исходного и целевого кластера.
Утилита pg_upgrade выполняет предварительную проверку обновляемого сервера, в результате которой могут возникнуть ошибки для:
Устаревших типов данных.
Неподдерживаемого синтаксиса.
Объектов, у которых изменилось физическое хранение данных, и перенести их данные копированием файлов нельзя, например, для индексов партиционированных таблиц. В этом случае нужно будет удалить индекс и создать его уже на новом кластере.
Отсутствующих расширений.
pg_upgrade в случае наличия объектов, данные которых нельзя перенести копированием файлов, выдаст ошибку. Такие объекты нужно перенести отдельно и это может быть все равно намного быстрее, чем перенос всех данных с помощью логического бэкапа. Такой перенос может выполнить ggupgrade с помощью дополнительных скриптов, которые будут описаны ниже в этой статье.
При возникновении ошибок со старым кластером ничего не происходит, с ним можно продолжать работать. Можно устранить ошибки и запустить pg_upgrade заново. Надо отметить, что при выполнении миграции на следующую версию через логический бэкап большая часть вышеописанных ошибок также может возникнуть.
Перед обновлением кластера рекомендуется внимательно ознакомиться с изменениями в версии, на которую планируется обновляться.
Обновление Greengage с помощью утилиты pg_upgrade
Так как Greengage состоит из множества инстансов PostgreSQL, то за основу для реализации утилиты обновления Greengage можно взять pg_upgrade PostgreSQL.
В Greengage есть объекты, которых нет в PostgreSQL, например append-optimized таблицы. Для таких таблиц существуют служебные таблицы, структура которых также может измениться в новой мажорной версии, поэтому перенести данные этих таблиц с помощью копирования файлов (или жестких ссылок) не удастся. Речь идет о служебных таблицах:
pg_aocssegpg_aovisimappg_aoblkdir
Неоптимальным будет генерировать и выполнять создание объектов на всех сегментах кластера Greengage. Так как структура объектов в кластере (метаинформация) на всех сегментах одинакова, то не нужно каждый раз создавать все объекты на всех сегментах кластера. Достаточно создать объекты на координаторе и скопировать полученные файлы системного каталога кластера с координатора на сегменты. На сегментах остается запустить копирование или создание жестких ссылок файлов данных.
Таким образом, утилита pg_upgrade для Greengage — это утилита pg_upgrade PostgreSQL, доработанная для объектов Greengage, а также оптимизированная на обновление метаинформации. Для этого у нее есть два режима запуска:
dispatcher— запуск на координаторе для формирования метаинформации.segment— запуск на сегментах для переноса данных.
Перед запуском pg_upgrade необходимо остановить исходный и целевой кластеры.
Схема обновления кластера Greengage с помощью утилиты pg_upgrade выглядит следующим образом:
Запуск
pg_upgradeна координаторе для создания объектов БД с теми же идентификаторами, что и на кластере предыдущей версии, в режимеdispatcher:
pg_upgrade на координаторе Копирование файлов метаинформации на сегменты:

Копирование метаинформации на сегменты Запуск
pg_upgradeна primary-сегментах для копирования файлов данных или создания жестких ссылок (параметр--link):
pg_upgrade на primary-сегментах Запуск gprecoverseg для восстановления mirror-сегментов.
Пересоздание standby с помощью gpinitstandby.
После запуска, обновления статистики и проверки кластера новой версии можно удалить старый кластер, для этого pg_upgrade генерирует скрипты.
Далее приведен пример обновления кластера Greengage 6 до Greengage 7 на Ubuntu 22.04, где уже установлен и инициализирован кластер версии 7. Этот пример представлен для понимания, как происходит мажорное обновление Greengage и его можно повторить на тестовых кластерах Greengage.
Выполнение обновления кластера Greengage 6 до Greengage 7 на Ubuntu 22.04
Для обновления кластера Greengage сначала необходимо установить Greengage новой версии на все хосты кластера текущей версии. Доработанная утилита pg_upgrade идет в составе Greengage 7.
Установка и инициализация кластера Greengage достаточно подробно описаны в документации Greengage. Чтобы исключить конфликты при установке утилиты inetutils-ping в Ubuntu, уберем ее из установки зависимостей для Ubuntu перед запуском README.Ubuntu.bash, так как она уже была ранее установлена для Greengage 6:
# удаляем установку inetutils-ping из файла README.Ubuntu.bash $ sed -i 's/inetutils-ping / /g' README.Ubuntu.bash
После установки бинарных файлов Greengage 7 на все хосты кластера необходимо инициализировать его на координаторе с помощью gpinitsystem той же самой конфигурации (с таким же количеством хостов и сегментов, а также набором расширений), что и обновляемый кластер.
Ниже приведены примеры команд для обновления кластера. Переходить на следующий этап нужно после того, как успешно выполнился предыдущий.
1. Обновление метаинформации на координаторе
Для обновления на координаторе необходимо остановить кластеры версий 6 и 7 и выполнить следующие команды:
# установка путей до Greengage # /usr/local/gpdb7 - директория, где установлен Greengage 7 # /ggdb7/data1/master/gpseg-1 - директория данных координатора # 5433 - порт кластера Greengage 7 $ source /usr/local/gpdb7/greengage_path.sh && export MASTER_DATA_DIRECTORY=/ggdb7/data1/master/gpseg-1 && export PGPORT=5433 # запуск утилиты pg_upgrade, установленной с Greengage 7 # /usr/lib/gpdb/bin - директория с бинарными файлами Greengage 6 # /usr/local/gpdb7/bin - директория с бинарными файлами Greengage 7 # /data1/master/gpseg-1 - директория данных кластера Greengage 6 # /ggdb7/data1/master/gpseg-1 - директория данных кластера Greengage 7 $ pg_upgrade -b /usr/lib/gpdb/bin -B /usr/local/gpdb7/bin -d /data1/master/gpseg-1 -D /ggdb7/data1/master/gpseg-1 --mode=dispatcher
В случае возникновения ошибок можно продолжать работу со старым кластером. Обновление до новой версии не будет выполнено.
Для устранения ошибок при обновлении необходимо:
Заменить объекты в исходном кластере с учетом различий версий 6 и 7 Greengage.
Установить необходимые расширения на новом кластере, которые использовались в исходном.
Объекты, которые нельзя перенести с помощью копирования файлов данных и по которым возникли ошибки, выгрузить отдельно и удалить перед повторным обновлением. Это, например, таблицы, содержащие составные системные типы данных, индексы партиционированных таблиц. После обновления выгруженные объекты нужно будет отдельно загрузить на новый кластер.
После устранения проблем и повторного запуска pg_upgrade на координаторе в случае успешного выполнения будет выведена следующая информация:
Performing Consistency Checks ----------------------------- Checking cluster versions ok Checking database user is the install user ok Checking database connection settings ok Checking for prepared transactions ok Checking for system-defined composite types in user tables ok ...
Полный вывод
Performing Consistency Checks ----------------------------- Checking cluster versions ok Checking database user is the install user ok Checking database connection settings ok Checking for prepared transactions ok Checking for system-defined composite types in user tables ok Checking for reg* data types in user tables ok Checking for contrib/isn with bigint-passing mismatch ok Checking for online expansion status ok Checking for external tables used in partitioning ok Checking for non-covering indexes on partitioned AO tables ok Checking for indexes on partitioned tables ok Checking for orphaned TOAST relations ok Checking array types derived from partitions ok Checking for multi-column LIST partition keys ok Checking for functions dependent on plpython2 ok Checking for views with removed operators ok Checking for views with removed functions ok Checking for views with removed types ok Checking for disallowed OPERATOR => ok Checking for SHA-256 hashed passwords ok Checking for removed "abstime" data type in user tables ok Checking for removed "reltime" data type in user tables ok Checking for removed "tinterval" data type in user tables ok Checking for tables WITH OIDS ok Checking for invalid "sql_identifier" user columns ok Checking for invalid "unknown" user columns ok Checking for roles starting with "pg_" ok Checking for appendonly materialized view with relfrozenxid ok Creating dump of global objects ok Creating dump of database schemas ok Checking for presence of required libraries ok Checking database user is the install user ok Checking for prepared transactions ok Checking for new cluster tablespace directories ok If pg_upgrade fails after this point, you must re-initdb the new cluster before continuing. Performing Upgrade ------------------ Analyzing all rows in the new cluster ok Freezing all rows in the new cluster ok Setting next distributed transaction ID for new cluster ok Deleting files from new pg_xact ok Copying old pg_clog to new server ok Setting oldest XID for new cluster ok Setting next transaction ID and epoch for new cluster ok Deleting files from new pg_multixact/offsets ok Copying old pg_multixact/offsets to new server ok Deleting files from new pg_multixact/members ok Copying old pg_multixact/members to new server ok Setting next multixact ID and offset for new cluster ok Resetting WAL archives ok Setting next OID for new cluster ok Deleting files from new pg_distributedlog ok Copying old pg_distributedlog to new server ok Setting frozenxid and minmxid counters in new cluster ok Restoring global objects in the new cluster ok Restoring database schemas in the new cluster ok Invalidating bitmap indexes in new cluster ok Freezing all rows in new master after pg_restore ok Copying user relation files ok Sync data directory to disk ok Creating script to analyze new cluster ok Creating script to delete old cluster ok Checking for hash indexes ok Checking for extension updates ok 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
2. Копирование файлов метаинформации с координатора на primary-сегменты
Для начала очистим директории данных на primary-сегментах:
# segment_hosts.hosts - файл с описанием всех сегментных хостов кластера # /ggdb7/data1/primary/data - вспомогательная директория $ gpssh -f segment_hosts.hosts -e 'rm -r /ggdb7/data1/primary/*/*/' && \ gpssh -f segment_hosts.hosts -e 'mkdir /ggdb7/data1/primary/data'
Скопируйте файлы данных на каждый primary-сегмент каждого сегментного хоста:
# копирование данных $ gpscp -f segment_hosts.hosts -r /ggdb7/data1/master/gpseg-1/*/ =:/ggdb7/data1/primary/data && \ gpssh -f segment_hosts.hosts -e 'find /ggdb7/data1/primary -type d -name "gpseg*" -exec cp -r /ggdb7/data1/primary/data/* {} \;' && \ # удаление вспомогательной директории gpssh -f ~/segment_hosts.hosts -e 'rm -r /ggdb7/data1/primary/data'
3. Запуск pg_upgrade на всех сегментах
Для запуска pg_upgrade в режиме копирования файлов на всех сегментах можно воспользоваться следующей командой на координаторе:
# запуск утилиты pg_upgrade, установленной с Greengage 7, на сегментах # /usr/lib/gpdb/bin - директория с бинарными файлами Greengage 6 # /usr/local/gpdb7/bin - директория с бинарными файлами Greengage 7 # /data1/primary - директория данных primary-сегментов кластера Greengage 6 # /ggdb7/data1/primary - директория данных primary-сегментов кластера Greengage 7 $ gpssh -f segment_hosts.hosts -e 'source /usr/local/gpdb7/greengage_path.sh && for dir in $(ls /ggdb7/data1/primary) ; do pg_upgrade -b /usr/lib/gpdb/bin -B /usr/local/gpdb7/bin -d /data1/primary/$dir -D /ggdb7/data1/primary/$dir --mode=segment; done'
Чтобы запустить pg_upgrade в режиме жестких ссылок, необходимо добавить параметр --link:
$ gpssh -f segment_hosts.hosts -e 'source /usr/local/gpdb7/greengage_path.sh && for dir in $(ls /ggdb7/data1/primary) ; do pg_upgrade -b /usr/lib/gpdb/bin -B /usr/local/gpdb7/bin -d /data1/primary/$dir -D /ggdb7/data1/primary/$dir --mode=segment --link; done'
При отсутствии ошибок для каждого сегмента должна быть выведена следующая информация:
Performing Consistency Checks ----------------------------- Checking cluster versions ok Checking database user is the install user ok Checking database connection settings ok Checking for prepared transactions ok Checking for system-defined composite types in user tables ok ...
Полный вывод
Полный вывод
Performing Consistency Checks ----------------------------- Checking cluster versions ok Checking database user is the install user ok Checking database connection settings ok Checking for prepared transactions ok Checking for system-defined composite types in user tables ok Checking for reg* data types in user tables ok Checking for contrib/isn with bigint-passing mismatch ok Checking for external tables used in partitioning ok Checking for non-covering indexes on partitioned AO tables ok Checking for indexes on partitioned tables ok Checking for orphaned TOAST relations ok Checking array types derived from partitions ok Checking for multi-column LIST partition keys ok Checking for functions dependent on plpython2 ok Checking for views with removed operators ok Checking for views with removed functions ok Checking for views with removed types ok Checking for disallowed OPERATOR => ok Checking for SHA-256 hashed passwords ok Checking for removed "abstime" data type in user tables ok Checking for removed "reltime" data type in user tables ok Checking for removed "tinterval" data type in user tables ok Checking for tables WITH OIDS ok Checking for invalid "sql_identifier" user columns ok Checking for invalid "unknown" user columns ok Checking for roles starting with "pg_" ok Checking for appendonly materialized view with relfrozenxid ok Checking for presence of required libraries ok Checking database user is the install user ok Checking for prepared transactions ok Checking for new cluster tablespace directories ok If pg_upgrade fails after this point, you must re-initdb the new cluster before continuing. Performing Upgrade ------------------ Freezing all rows in the new cluster ok Setting next distributed transaction ID for new cluster ok Deleting files from new pg_xact ok Copying old pg_clog to new server ok Setting oldest XID for new cluster ok Setting next transaction ID and epoch for new cluster ok Deleting files from new pg_multixact/offsets ok Copying old pg_multixact/offsets to new server ok Deleting files from new pg_multixact/members ok Copying old pg_multixact/members to new server ok Setting next multixact ID and offset for new cluster ok Resetting WAL archives ok Setting next OID for new cluster ok Deleting files from new pg_distributedlog ok Copying old pg_distributedlog to new server ok Restoring append-only auxiliary tables in new cluster ok Copying user relation files ok Setting database system identifier for new cluster ok Sync data directory to disk ok Creating script to analyze new cluster ok Creating script to delete old cluster ok Checking for hash indexes ok Checking for extension updates ok 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
4. Проверка обновленного кластера и запуск gprecoverseg
После выполнения обновления нужно запустить кластер версии 7, проверить его работоспособность и запустить восстановление зеркал:
# установка пути до Greengage 7 $ source /usr/local/gpdb7/greengage_path.sh && export MASTER_DATA_DIRECTORY=/ggdb7/data1/master/gpseg-1 && export PGPORT=5433 # запуск кластера версии 7 $ gpstart # проверка $ psql postgres # восстановление зеркал $ gprecoverseg -F
Сравнение gpbackup/gprestore с pg_upgrade для обновления Greengage с версии 6 на 7
Проводилось сравнение обновления Greengage с версии 6 на версию 7 с помощью логического бэкапа и с помощью pg_upgrade на одном и том же кластере.
Кластер Greengage состоял из координатора и двух сегментных хостов со следующими параметрами.
Тип | CPU | RAM | HDD | Размер данных |
|---|---|---|---|---|
Координатор | 8 | 32 ГБ | 150 ГБ | 17 ГБ |
Сегмент 1 | 16 | 32 ГБ | 1,5 ТБ | 364 ГБ (primary) + 360 ГБ (mirror) |
Сегмент 2 | 16 | 32 ГБ | 1,5 ТБ | 364 ГБ (primary) + 360 ГБ (mirror) |
В базе данных кластера было 90 000 равномерно заполненных таблиц, из которых было 76 000 append-optimized таблиц.
Были получены следующие результаты.
gpbackup/gprestore | |
Операция | Затраченное время |
|---|---|
| 1 ч 10 мин |
| 1 ч |
Создание метаинформации | 10 мин |
| 5 ч 7 мин |
| 5 ч 8 мин |
Общее время | 6 ч 18 мин |
pg_upgrade | |
Операция | Затраченное время |
|---|---|
| 10 мин |
Копирование метаинформации на сегменты | 5 мин |
Обновление сегментов в режиме копирования файлов | 1 ч 50 мин |
Обновление сегментов в режиме жестких ссылок ( | 15 мин |
Общее время в режиме копирования файлов | 2 ч 5 мин |
Общее время в режиме жестких ссылок | 25 мин |
В случае режима копирования файлов pg_upgrade быстрее в 3 раза, чем миграция данных с помощью логического бэкапа. В режиме создания жестких ссылок на данные pg_upgrade выигрыш составляет 15 раз. Выигрыш по переносу данных pg_upgrade составил 20 раз! Есть еще одно преимущество режима жестких ссылок для pg_upgrade: так как сами данные не копируются, а на них создаются ссылки, то свободного места потребуется гораздо меньше — только на метаинформацию и некоторые отдельно перенесенные объекты.
Обновление Greengage с помощью утилиты ggupgrade
Отличные результаты pg_upgrade мотивируют развивать дальше этот механизм. Как видно из вышеприведенного примера обновления Greengage с помощью pg_upgrade, пользователю необходимо выполнить достаточно много ручных действий.
Чтобы автоматизировать эту работу, была создана утилита ggupgrade, которая выполняет следующее:
инициализирует новый кластер;
выполняет дополнительные скрипты на старом кластере;
запускает
pg_upgradeна координаторе;копирует метаинформацию на все сегменты;
запускает
pg_upgradeна всех primary-сегментах;запускает скрипты на новом кластере;
обновляет standby и зеркала;
настраивает новый кластер на использование порта старого кластера.
Здесь можно отметить, что в случае pg_upgrade кластер новой версии приходилось сначала инициализировать, а ggupgrade делает это самостоятельно на основе конфигурации старого кластера.
Добавлена интересная функция — выполнение дополнительных скриптов. Дополнительные скрипты — это скрипты, которые позволяют обходить некоторые проблемы при обновлении с помощью pg_upgrade. Например, в случае индексов для партиционированных таблиц в дополнительных скриптах будет генерация команд создания этих индексов для дальнейшего выполнения на новом кластере и их предварительное удаление на старом кластере. Пользователь может включать собственные дополнительные скрипты.
Для того чтобы выполнить обновление кластера с помощью ggupgrade, пользователю нужно:
Установить новую версию Greengage на все хосты обновляемого кластера.
Установить/скопировать утилиту
ggupgradeна все хосты обновляемого кластера.Скопировать дополнительные скрипты на координатор.
Установить путь до
ggupgradeвPATHна координаторе.Настроить конфигурационный файл на координаторе.
Пример содержимого конфигурационного файла ggupgrade_config для
ggupgrade:# The source cluster master port. source_master_port = 5432 # The installation path for the source cluster. # For example, /usr/local/<source-greengage-version>. source_gphome = /usr/lib/gpdb # The installation path for the target cluster. # For example, /usr/local/<target-greengage-version>. target_gphome = /usr/local/gpdb7 # Whether to upgrade using "link" or "copy" mode. # The copy method performs the upgrade on a copy of the primary segments. # The link method directly upgrades the primary segments. mode = linkЗапустить
ggupgradeна координаторе. Есть 4 основных этапа работы утилиты:initialize, где происходит инициализация кластера версии 7, запуск дополнительных скриптов, сбор статистики, а также проверка на наличие возможных проблем при обновлении.execute, где запускаетсяpg_upgradeна координаторе и всех сегментах с копированием метаинформации с координатора на сегменты.revert, при запуске которого кластер версии 6 восстанавливается в исходное состояние. Этот режим можно запускать на любом этапе до этапаfinalize.finalize, на этом этапе запускаются дополнительные скрипты, обновление статистики, а также запуск обновленного кластера на порте исходного кластера.
Пример запуска
ggupgrade:# этап инициализации $ ggupgrade initialize -v -f /opt/ggupgrade/ggupgrade_config # этап выполнения $ ggupgrade execute # этап финализации $ ggupgrade finalize
Заключение
Текущие версии pg_upgrade и ggupgrade уже показывают отличные результаты. Приглашаем всех желающих испытать их на прочность на своих тестовых стендах — ваша обратная связь важна для финального релиза.
