Миграция PostgreSQL под ОС AstraLinux c использованием pgcopydb с PG11 на PG15

от автора

Многие в настоящее время сталкиваются с необходимостью миграции с AstraLinux 1.7 на AstraLinux 1.8.

Для тех, кто пользуется штатной PostgreSQL 11 из поставки AstraLinux 1.7, встает во весь рост вопрос, как перетащить существующие базы на новую версию. Если базы маленькие, особых проблем нет. А вот если базу под 1ТБ, то проблемы встают в полный рост.

Для штатной pg_upgrade требуются обе версии (PostgreSQL-11 и PostgreSQL-15). Но в поставке AstraLinux 1.8 нет PostgreSQL 11. При этом, так как Astra PostgreSQL не совместим бинарно с «Ванилью», то и не получится собрать самому нужную версию для Astra 1.8.

«Вкорячить» его из поставки Astra 1.7 можно, но не гарантирует работоспособность. (Напишу заметку об этом позже).

Штатный pg_dump | pg_restore в одну нитку, для базы 1.1 Тб у нас на стенде работал аж 27 часов. Максимальный размер технологического окна при этом установлен 24 часа.

Может быть еще одна причина для выбора pg_dump/pg_restore варианта — если datafile исходной базы и целевой базы бинарно несовместимы. Как например несовместимы между собой datafiles наиболее часто использующихся дистрибутивов PostgreSQL:

  • «Ваниль»

  • PostgresPro EE/SE

  • Tantor

  • Штатная PostgreSQL AstraLinux

Поиск решения (помимо логической репликации), навел на утилиту pgcopydb

Для начала засады:

1) в Astra1.8 в PostgreSQL уменьшили длину типа name с 255 байт до 63.

https://docs.astralinux.ru/latest/guide/application/devfeature/

Поэтому, при использовании длинных идентификаторов (имен) возникают ошибки при pg_dump15/pg_restore15 при работе с PostgreSQL-11. При этом утилиты pg11 без проблем работают с PostgreSQL-15.

Из-за этого, для миграции с использованием pgcopydb его нужно собирать именно на astra1.7.

2)  pgcopydb не понимает MAC LABEL SECURITY

3) PG12+: больше не поддерживается созданием таблиц с кляузой «WITH OIDS»

Ранее в таблицу можно было добавить столбец oid (невидимый в обычных запросах), создавая её с указанием WITH OIDS; теперь такой возможности нет. При этом по-прежнему возможно создавать столбцы с типом oid. С учётом этого изменения порядок использования таблиц, созданных с указанием WITH OIDS, потребуется скорректировать.

Системные каталоги, в которых были скрытые столбцы oid, теперь содержат обычные столбцы oid. Таким образом, эти столбцы будут выводиться в результате запроса SELECT *, тогда как ранее они выводились только в случае явного указания.

Сборка pgcopydb

Сборку рекомендуется выполнять на отдельной машине, так как средства разработки не допускаются в закрытом контуре.

apt-get install -y --no-install-recommends \   git \   build-essential \   autotools-dev \   libedit-dev \   libgc-dev \   libpam0g-dev \   libreadline-dev \   libselinux1-dev \   libxslt1-dev \   libssl-dev \   libkrb5-dev \   zlib1g-dev \   liblz4-dev \   libpq5 \   libpq-dev \   libzstd-dev \   postgresql-server-dev-all \   postgresql-common \   postgresql \   python3-sphinx  git clone https://github.com/dimitri/pgcopydb  cd pgcopydb make

Инсталляция pgcopydb на другую машину

Для инсталляции нужен только сам исполняемый файл pgcopydb и библиотека libgc.so.1

## Скопировать полученный файл на нужную машину scp src/bin/pgcopydb/pgcopydb targethost:bin/   ## разрешить установку права запуска для файлов sudo astra-nochmodx-lock disable  ## добавляем возможность запуска chmod 0755 pgcopydb  ## доставить библиотеку libgc.so.1 apt install libgc1c2

Так, как pgcopydb не понимает MAC LABEL SECURITY, ставим обертку для pg_dump, pg_restore, pg_dumpall

cd /usr/lib/postgresql/11/bin  mv pg_dump pg_dump.bin mv pg_dumpall pg_dumpall.bin mv pg_restore pg_restore.bin  ## добавляем опции отключающие MAC LABEL echo "/usr/lib/postgresql/11/bin/pg_dump.bin --no-security-labels --disable-macs $@" > pg_dump echo "/usr/lib/postgresql/11/bin/pg_dumpbin.bin --no-security-labels $@" > pg_dumpall echo "/usr/lib/postgresql/11/bin/pg_restore.bin --no-security-labels $@" > pg_restore chmod 0755 pg_dump pg_dumpall pg_restore

Подготовка исходной базы

Правим длинные имена

получить список объектов для поля типа name > 63 bytes

Для этого тупо генерируем запросы select … from object where length(name) > 63 для всех объектов где есть поле name, и выполняем полученный tmp.sql в отдельном шаге.

Готовим файл запроса полей name и формирования запросов к каждой такой таблице (файл q1.sql):

select   'SELECT '''||table_schema||'.'||table_name||'.'||column_name||': ''||'|| column_name ||     ' FROM "'||table_schema||'"."'||table_name||'" WHERE '||'length("'||column_name||'") > 63;'  from information_schema.columns where data_type = 'name' ;

Выполняем следующую команду:

## для каждой базы, формируем tmp.sql и потом выполняем его для получения списка объектов psql -AXtc "select datname from pg_database"|while read db   do echo "==== $db =====";  psql -AXt -d $db -f q1.sql > tmp.sql  psql -d $db -AtX -f tmp.sql > $db.txt done

Передаем полученный список разработчикам, чтобы убрали длинные имена.

Правим «WITH OIDS» у таблиц

Получаем команды для правки таблиц

-- генерация команд для правки таблиц   SELECT 'ALTER TABLE "' || n.nspname || '"."' || c.relname || '" SET WITHOUT OIDS;' FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE 1=1   AND c.relkind = 'r'   AND c.relhasoids = true   AND n.nspname <> 'pg_catalog' order by n.nspname, c.relname;  
-- выполняем полученные команды, например test=# ALTER TABLE "abc"."recipients_m11" SET WITHOUT OIDS; ALTER TABLE test=#  ALTER TABLE "abc"."config_m11" SET WITHOUT OIDS; ALTER TABLE test=#  ALTER TABLE "abc"."data_m11" SET WITHOUT OIDS;

Подготовка целевой базы

Тут все просто, шаги те же что и для обычного pg_dump/pg_restore

например:

создаем базу с нужным owner

переносим роли и extension

# first two commands would use a superuser role $ pgcopydb copy roles --source ... --target ... $ pgcopydb copy extensions --source ... --target ...

Можно запускать pgcopydb для миграции

export PGCOPYDB_SOURCE_PGURI="postgres://user@source.host.dev/dbname" export PGCOPYDB_TARGET_PGURI="postgres://role@target.host.dev/dbname"  pgcopydb clone --table-jobs 4 --index-jobs 4


ссылка на оригинал статьи https://habr.com/ru/articles/882192/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *