[Документация Yandex Cloud](../../index.md) > [Практические руководства](../index.md) > [Построение Data Platform](index.md) > Миграция БД из Managed Service for PostgreSQL

# Миграция базы данных из Managed Service for PostgreSQL

Кластер Managed Service for PostgreSQL поддерживает [логическую репликацию](https://www.postgresql.org/docs/current/logical-replication.html). Это позволяет мигрировать базы данных встроенными средствами PostgreSQL между разными кластерами PostgreSQL версий 10 и выше. В том числе поддерживается миграция между разными версиями: например, можно перенести базы из PostgreSQL версии 15 в версию 17.

{% note info %}

Если вы используете кластеры более старых версий, то можно мигрировать базу, [создав дамп](https://www.postgresql.org/docs/current/app-pgdump.html) и затем [восстановившись](https://www.postgresql.org/docs/current/app-pgrestore.html) из него.

{% endnote %}

Этот сценарий использования описывает, как перенести базу данных из сервиса Managed Service for PostgreSQL в другой кластер PostgreSQL с помощью логической репликации.

Чтобы мигрировать базу данных из *кластера-источника* Managed Service for PostgreSQL в *кластер-приемник* PostgreSQL:
1. [Перенесите схему базы данных](#migrate-schema).
1. [Настройте пользователя для управления репликацией на кластере-источнике](#configure-user).
1. [Создайте публикацию на кластере-источнике](#create-publication).
1. [Создайте подписку на кластере-приемнике](#create-subscription).
1. [Отслеживайте процесс миграции](#monitor-migration) до его завершения.
1. [Закончите миграцию](#finish-migration).

Если созданные ресурсы вам больше не нужны, [удалите их](#clear-out).


## Необходимые платные ресурсы {#paid-resources}

* Кластер Managed Service for PostgreSQL: выделенные хостам вычислительные ресурсы, объем хранилища и резервных копий ([тарифы Managed Service for PostgreSQL](../../managed-postgresql/pricing.md)).
* Публичные IP-адреса, если для хостов кластеров включен публичный доступ ([тарифы Virtual Private Cloud](../../vpc/pricing.md)).


## Перед началом работы {#before-you-begin}

1. Убедитесь, что все хосты кластера-источника доступны по публичному IP-адресу, чтобы кластер-приемник мог подключаться к источнику. Подробнее в разделе [Создание кластера](../../managed-postgresql/operations/cluster-create.md).
1. Установите на хосты кластера-приемника [клиентские SSL-сертификаты Managed Service for PostgreSQL](../../managed-postgresql/operations/connect/index.md#get-ssl-cert). Они требуются для успешного подключения к публично доступному кластеру-источнику.


1. При необходимости настройте межсетевой экран (firewall) и [группы безопасности](../../managed-postgresql/operations/connect/index.md#configuring-security-groups), чтобы можно было подключаться из кластера-приемника к кластеру-источнику, а также к каждому кластеру в отдельности (например, с помощью утилиты [psql](https://www.postgresql.org/docs/current/app-psql.html)).


1. Убедитесь, что с хостов кластера-приемника можно подключиться к хостам кластера-источника.
1. Убедитесь, что можно [подключиться к кластеру-источнику](../../managed-postgresql/operations/connect/index.md) с помощью SSL и к кластеру-приемнику.
1. Убедитесь, что на кластере-приемнике создана пустая база данных, в которую будет проведена миграция. 
1. Убедитесь, что в кластере-приемнике существует пользователь с полными правами на доступ к этой базе.

## Перенесите схему базы данных {#migrate-schema}

Для успешной работы логической репликации необходимо, чтобы и на источнике, и на приемнике была одинаковая схема базы данных. Чтобы перенести схему базы данных:
1. Сделайте дамп схемы базы данных кластера-источника с помощью утилиты [pg_dump](https://www.postgresql.org/docs/current/app-pgdump.html):

   ```bash
   pg_dump "host=<FQDN_хоста_кластера-источника> port=6432 sslmode=verify-full dbname=<имя_БД> user=<имя_пользователя-владельца_БД>" --schema-only --no-privileges --no-subscriptions --no-publications -Fd -f <директория_для_дампа>
   ```
   
   FQDN хоста можно получить со [списком хостов в кластере](../../managed-postgresql/operations/hosts.md#list).
   
1. При необходимости создайте пользователей с нужными правами на доступ к объектам базы данных на кластере-приемнике.

1. Восстановите схему базы данных из дампа на кластере-приемнике с помощью утилиты [pg_restore](https://www.postgresql.org/docs/current/app-pgrestore.html):

   ```bash
   pg_restore -Fd -v --single-transaction -s --no-privileges -h <FQDN_хоста-мастера_кластера-приемника> -U <имя_пользователя-владельца_БД> -p 5432 -d <имя_БД> <директория_с_дампом>
   ```

## Настройте пользователя для управления репликацией на кластере-источнике {#configure-user}

PostgreSQL использует модель «публикация-подписка» при выполнении логической репликации: кластер-приемник *подписывается* на *публикацию* кластера-источника, чтобы перенести данные. Чтобы успешно подписаться на публикацию, к кластеру-источнику Managed Service for PostgreSQL нужно обращаться от имени пользователя, которому назначена роль для управления логической репликацией. Чтобы настроить такого пользователя:
1. [Создайте пользователя](../../managed-postgresql/operations/cluster-users.md#adduser).
1. [Назначьте роль](../../managed-postgresql/operations/grant.md#grant-role) `mdb_replication` этому пользователю.
1. [Подключитесь к базе данных](../../managed-postgresql/operations/connect/index.md), которую нужно мигрировать, от имени **владельца базы**.
1. [Выдайте созданному пользователю привилегию](../../managed-postgresql/operations/grant.md#grant-privilege) на выполнение операции `SELECT` над всеми таблицами базы данных.

После [создания подписки](#create-subscription) подключение к кластеру-источнику со стороны приемника будет осуществляться от имени этого пользователя.

## Создайте публикацию на кластере-источнике {#create-publication}

1. [Подключитесь](../../managed-postgresql/operations/connect/index.md) к **хосту-мастеру** и к базе данных, которую нужно мигрировать, от имени **владельца базы**.
1. Создайте публикацию, на которую будет подписываться кластер-приемник:

   ```sql
   CREATE PUBLICATION <имя_публикации>;
   ```
   
1.  Включите в созданную публикацию все таблицы базы данных:

    ```
    ALTER PUBLICATION <имя_публикации> ADD TABLE <имя_таблицы_1>;
    ...
    ALTER PUBLICATION <имя_публикации> ADD TABLE <имя_таблицы_N>;
    ``` 
    
    {% note info %}
    
    В кластере Managed Service for PostgreSQL запрещено создание публикации сразу для всех таблиц `CREATE PUBLICATION ... FOR ALL TABLES;`, т.к. это требует привилегий суперпользователя.
    
    {% endnote %}
    
## Создайте подписку на кластере-приемнике {#create-subscription}

1. Подключитесь к **хосту-мастеру** и базе данных, в которую нужно выполнить миграцию, от **имени суперпользователя** (например, `postgres`).
1. Создайте подписку на публикацию кластера-источника:

   ```sql
   CREATE SUBSCRIPTION <имя_подписки> CONNECTION 'host=<FQDN_хоста_кластера-источника> port=6432 sslmode=verify-full dbname=<имя_БД_которую_нужно_мигрировать> user=<имя_пользователя_для_управления_репликацией> password=<пароль_пользователя>' PUBLICATION <имя_публикации>;
   ```
   
Начнется процесс миграции данных из базы кластера-источника в базу кластера-приемника.

## Отслеживание процесса миграции {#monitor-migration}

Следите за миграцией с помощью каталога [pg_subscription_rel](https://www.postgresql.org/docs/current/catalog-pg-subscription-rel.html), который показывает *статус репликации*:

```sql
SELECT * FROM pg_subscription_rel;

 srsubid | srrelid | srsubstate | srsublsn
---------+---------+------------+----------
...
```

Рекомендуется следить за статусом репликации по полю `srsubstate` этого каталога на кластере-приемнике.

Общий статус репликации на кластере-приемнике можно получить с помощью представления (view) [pg_stat_subscription](https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-SUBSCRIPTION), на источнике — с помощью представления [pg_stat_replication](https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-REPLICATION-VIEW).

## Закончите миграцию {#finish-migration}

После завершения процесса репликации:
1. Запретите запись в смигрированную базу данных на кластере-источнике.

1. Перенесите последовательности (sequences), если они есть, из кластера-источника на кластер-приемник с помощью утилит pg_dump и psql:

   ```bash
   pg_dump "host=<FQDN_хоста-мастера_кластера-источника> port=6432 sslmode=verify-full dbname=<имя_БД> user=<имя_пользователя-владельца_БД>" --data-only -t '*.*_seq' > <имя_файла_с_sequences>
   ```
   
   ```bash
   psql -h <FQDN_хоста-мастера_кластера-приемника> -U <имя_пользователя-владельца_БД> -p 5432 -d <имя_БД> < <имя_файла_с_sequences>
   ``` 

1. Удалите подписку на кластере-приемнике:

   ```sql
   DROP SUBSCRIPTION <имя_подписки>;
   ```
   
1. Удалите публикацию на кластере-источнике:

   ```sql
   DROP PUBLICATION <имя_публикации>;
   ```
   
1. [Удалите пользователя](../../managed-postgresql/operations/cluster-users.md#removeuser) для управления репликацией на кластере-источнике.

## Удалите созданные ресурсы {#clear-out}

Удалите ресурсы, которые вы больше не будете использовать, чтобы за них не списывалась плата:

* [Удалите виртуальную машину](../../compute/operations/vm-control/vm-delete.md).
* Если вы зарезервировали для виртуальной машины публичный статический IP-адрес, [удалите его](../../vpc/operations/address-delete.md).
* [Удалите кластер Yandex Managed Service for PostgreSQL](../../managed-postgresql/operations/cluster-delete.md).