DevOps Linux

Перенос БД PostgreSQL 10.1 в AWS RDS PostgreSQL 10.5.

22.01.2020

Рассмотрим перенос данных базы «l_generator» с помощью Londiste.

Почему Londiste?
Рекомандация использовать Londiste от Amazon:
https://aws.amazon.com/ru/blogs/aws/rds-postgres-read-replicas/ — 2014

Data Import (Londiste)
In order import data using Londiste, you would need to install it on the external PostgreSQL instance (not on RDS), set up RDS PostgreSQL instance as a replica, and enable replication. Londiste would initially do a dump and load of data into RDS PostgreSQL instance while the external instance is still taking write traffic. Over time, the RDS instance will catch up with the updates that are taking place on the external instance. Once the RDS instance is current, you can then point your applications to the RDS PostgreSQL instance, choosing the timing so as to minimize application downtime.

Data Export (Bucardo)
You can also use the session role to export data from an RDS for PostgreSQL instance to a remote target on-premises or on EC2. There are many ways to do this. For example, you can install Bucardo, an open source trigger-based lazy replication solution on the remote instance and set it up as a replication slave to the master RDS PostgreSQL instance. Bucardo replicates the data on the RDS instance to the remote instance as long as the remote instance is online. With lazy replication, when the remote instance goes offline and comes back online, Bucardo ensures that the remote instance will eventually catch up.

Инстансы БД Amazon RDS для PostgreSQL, использующие версию PostgreSQL 9.3.5 и более новые, поддерживают роль репликации сессий. Импортировать данные на инстанс БД Amazon RDS для PostgreSQL с минимальным временем простоя можно также путем использования данной роли и запускаемых с помощью событий инструментов репликации с открытым исходным кодом, таких как Londiste.

Терминология:

Skytools — это приложение, написанное на Python и оно использует Python-Postgres драйвер «psycopg2». Версии 2.4.2 и 2.4.3 psycopg2 имеют проблемы с потерей данных и не должны использоваться с Londiste.
Ссылка: http://initd.org/psycopg/. Посленяя доступная версия 2.7.5.

Используем Skytools версии 2, т.к. Skytools3 не подходит — ему нужны права полноценного superadmin в RDS.

PGQ — это реализация очередей от Skytools. Londiste строит свою репликацию на основе очередей PGQ.
Ссылка: https://wiki.postgresql.org/wiki/PGQ_Tutorial

Londiste — это асинхронная система репликации, построенная поверх очередей PGQ. Он может быть запущен на любом сервере, но обычно его запускают на сервере с источником данных для переноса.

Provider — источник для репликации, в нашем случае это БД на ec2 инстансе; Subscriber — приемник для репликации, в нашем случае это AWS RDS с PostgreSQL 10.

Подготовка RDS к пареносу данных:

  1. Для начала необходимо создать руками базу данных на subscriber-е:
CREATE DATABASE l_generator;

Дать соответсующему пользователю права на эту базу

CREATE USER l_generator WITH ENCRYPTED PASSWORD 'superpassword';
GRANT ALL ON database l_generator to l_generator;

2. Затем нужно перенести схему этой базы с provider-a, чтобы создались все таблицы и индексы:

pg_dump -o -h 127.0.0.1 -U postgres_migrate -d l_generator -n public -s > public_schema_l_generator.dump

где «-n public» — переносить только схему public; «-s» — дампить только схему, без самих данных.

3. Накатываем схему на новую базу subscriber-a:

psql -h database.eu-west-1.rds.amazonaws.com -U l_generator -d l_generator -f public_schema_l_generator.dump

Если возникли ошибки при накатывании схемы в RDS:

CREATE INDEX
psql:public_schema_l_generator.dump:2168: ERROR:  data type integer has no default operator class for access method "gin"
HINT:  You must specify an operator class for the index or define a default operator class for the data type.
psql:public_schema_l_generator.dump:2175: ERROR:  data type integer has no default operator class for access method "gin"
HINT:  You must specify an operator class for the index or define a default operator class for the data type.

Не могут создаться индексы, поэтому создаём их сами

CREATE INDEX ads_ids_idx ON ads USING gin (ads_ids);
CREATE INDEX ads_per_run_id_ids_idx ON ads USING gin (project_run_id, ads_ids);
CREATE INDEX ads_per_run_id_ids_idx_1 ON ads USING gin (ads_ids, project_run_id);

Нужно установить необходимые экстеншены

CREATE EXTENSION btree_gin;
CREATE EXTENSION btree_gist;

Приступаем к установке londiste из пакета Skytools2.

Будем компилить из исходников последнюю версию.

  1. Install PostgreSQL:
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'

2. Установка psycopg2:
Доступные версии в репозиториях:

python-psycopg2/trusty 2.4.5-1build5 amd64 — (Ubuntu 14.04)

python-psycopg2/stretch-pgdg 2.7.5-2.pgdg90+1 amd64 — (Debian 9)

Debian 9:

apt install python-psycopg2

3. Загружаем последнюю версию Skytools2 с сайта:
http://pgfoundry.org/frs/?group_id=1000206
skytools 2.1.13 (2012-03-13 08:33)

wget http://pgfoundry.org/frs/download.php/3232/skytools-2.1.13.tar.gz
tar zxf skytools-2.x.x.tar.gz
cd skytools-2.x.x

4. Конфигурируем:
Конфигуратору нужно указать префикс — место, куда будет установлен skytools2 и скрипт для определения установленной версии postgresql:
ищем скрипт:

$ sudo find / -type f -name "pg_config"
/usr/bin/pg_config

конфигурируем:

./configure --prefix=/opt/skytools-2.1.13 --with-pgconfig=/usr/bin/pg_config

Возможные ошибки:

error: missing keywords.h:
sudo ln -s /usr/include/postgresql/10/server/common/keywords.h /usr/include/postgresql/10/server/parser/keywords.h
error: ‘SerializableSnapshot’ undeclared:

https://www.postgresql.org/message-id/CAGnEboibud6TtmnaJCmK9SNCpcHOKyq4%2BmHYMEb2EDVP2yofCg%40mail.gmail.com

Ive made another change than, that fixes PG version detection in the sql/txid/Makefile. With this patch I got skytoolsbuild fine here.

https://www.postgresql.org/message-id/attachment/57157/20171218-skytools-10.diff

pg83 = $(shell [ $( echo -e "$PGVER\n8.3"|sort -gt. -k1 -k2|head -n1 ) = $PGVER ] && echo false || echo true)
pg82 = $(shell test $(PGVER) "<" "8.2" && echo "false" || echo "true")  

sed -ie '/^pg83/s:shell test.*$:shell [ $( echo -e "$PGVER\\n8.3"|sort -gt. -k1 -k2|head -n1 ) = $PGVER ] \&\& echo false || echo true):' Makefile
sed -ie '/^pg82/s:shell test.*$:shell [ $( echo -e "$PGVER\\n8.2"|sort -gt. -k1 -k2|head -n1 ) = $PGVER ] \&\& echo false || echo true):' Makefile
error: CRITICAL Job live_master_db crashed: <class ‘psycopg2.OperationalError’

https://jmorano.moretrix.com/2014/11/skytools-2-x-patch-for-postgresql-9-3-5/
The fix:
Add to ”sql/pgq/triggers/common.c” (in the skytools 2.1.13 source directory) the following line:

#include "access/htup_details.h"

5. Выполняем make:

$ sudo apt install postgresql-server-dev-10
$ make 

6. Собираем .deb:

$ sudo mkdir /usr/share/doc/postgresql-doc-10
$ sudo checkinstall make install

6. Установим порцию python инструментов из пакета skytools:

$ python setup.py build
$ sudo python setup.py install

Конфигурируем:

  1. Настройка тикера для PGQ:
$ cat ticker.ini
[pgqadm]
job_name = ticker_for_l_generator
db = dbname=l_generator host=127.0.0.1 port=5432 user=postgres_migrate password=xxxxxxxxx

# how often to run maintenance [seconds]
maint_delay = 600

# how often to check for activity [seconds]
loop_delay = 0.1
logfile = log/%(job_name)s.log
pidfile = run/%(job_name)s.pid

2. Устанавливаем тикер в базу-источник (создается схема pgq со всем необходимым) и запускаем демон:

$ pgqadm.py ticker.ini install
$ pgqadm.py ticker.ini ticker -d

3. Конфигурируем Лондист:

$ cat londiste.ini
[londiste]
job_name = londiste_l_genertor_migrate_to_rds

provider_db = dbname=l_generator port=5432 host=127.0.0.1 user=postgres_migrate password=xxxxxxxxxxx
subscriber_db = dbname=l_generator port=5432 host=database.eu-west-1.rds.amazonaws.com user=l_generator password=xxxxxxxxx

# max locking time on provider (in seconds, float)
# lock_timeout = 100

# it will be used as sql ident so no dots/spaces
pgq_queue_name = londiste_queue
logfile = log/%(job_name)s.log
pidfile = run/%(job_name)s.pid

4. Устанавливаем Лондист в провайдер и сабскрайбер (создается схема londiste со всем необходимым):
Install Londiste:

$ londiste.py londiste.ini provider install
$ londiste.py londiste.ini subscriber install

5. Запускаем процесс репликации (пока еще не добавили таблицы для отслеживания):
Launch replication:

$ londiste.py londiste.ini replay -d

6. Добавляем таблицы в репликацию:

londiste.py londiste.ini provider add public.ad_system public.ads
londiste.py londiste.ini subscriber add public.ad_system public.ads

можно добавить все таблицы разом (но могут возникнуть ошибки по некоторым):

londiste.py londiste.ini provider tables | xargs londiste.py lonidste.ini subscriber add

Возможные ошибки:

psycopg2.extensions.QueryCanceledError: canceling statement due to statement timeout

Создание триггера не укладывается в заданный интервал statement_timeout. Londiste вызывает SET LOCAL statement_timeout = %d перекрывая тем самым системные настройки.
Изменяется параметр в конфиге лондиста параметром (по умолчанию = 10 сек):

lock_timeout = 100

psycopg2.InternalError: need key column

Нет ни одного индекса в таблице provider-а. Необходмо создать индекс:

ALTER TABLE ONLY ads_tmp ADD CONSTRAINT ads_tmp_pkey PRIMARY KEY (id);

7. Добавляем последовательности (сиквенсы) в репликацию:

londiste.py londiste.ini provider add-seq public.ad_system_id_seq
londiste.py londiste.ini subscriber add-seq public.ad_system_id_seq

можно добавить все сиквенсы разом:

londiste.py londiste.ini londiste.ini provider add-seq --all
londiste.py londiste.ini londiste.ini subscriber add-seq --all

Наблюдаем за процессом репликации:

Статус на провайдере в консоли psql:

Тут лаг — это отставание subscriber от provider. LastSeen — когда в прошлый раз сверялась очередь, Londiste работает с Batch — так называемыми пачками.

 SELECT queue_name, consumer_name, lag, last_seen
   FROM pgq.get_consumer_info();
  queue_name   |              consumer_name              |       lag       |    last_seen
----------------+-----------------------------------------+-----------------+-----------------
 londiste_queue | londiste_l_genertor_migrate_to_rds | 00:00:52.128794 | 00:00:51.350834
(1 row)
Статус тикера:
$ pgqadm.py ticker.ini status
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Postgres version: 10.1   PgQ version: 2.1.8

Event queue                                    Rotation        Ticker   TLag
------------------------------------------------------------------------------
londiste_queue                                  3/7200s    500/3s/60s    27s
------------------------------------------------------------------------------

Consumer                                                       Lag  LastSeen
------------------------------------------------------------------------------
londiste_queue:
  londiste_l_genertor_migrate_to_rds                      27s       27s
  londiste_l_genertor_migrate_to_rds_copy                207s      147s
------------------------------------------------------------------------------
Статус subscriber:
$ londiste.py londiste.ini subscriber tables
Table                                           State
public.ad_system                                   ok
public.ads                                    in-copy
public.adv_creator                                  -
public.adwords_disabled_ads                         -
public.alembic_version                              -
Какие переносятся последовательности:
$ londiste.py londiste.ini subscriber seqs
public.ad_system_id_seq
public.ads_id_seq

ССЫЛКИ:

https://wiki.postgresql.org/wiki/Londiste_Tutorial_%28Skytools_2%29
http://www.tothenew.com/blog/postgresql-on-linux-migration-to-aws-postgresql-rds-using-londiste-daemon-no-downtime/
https://wiki.dieg.info/skytools#upravlenie_skytools_2112 
http://evtuhovich.ru/blog/2009/05/22/live-table-migration/
https://wiki.postgresql.org/wiki/PGQ_Tutorial 

https://wiki.postgresql.org/images/2/28/Moskva_DB_Tools.v3.pdf

https://www.pgcon.org/2009/schedule/attachments/101_Londiste3.pdf 

https://aws.amazon.com/ru/rds/postgresql/details/ — используя роль репликации сессий (ALTER ROLE REPLICATION);

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

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