---
title: 'Миграция баз данных PostgreSQL в облачные базы данных PostgreSQL'
sidebar_label: 'Миграция в облачные базы данных'
sidebar_position: 22
description: 'Как перенести базу данных PostgreSQL в облачные базы данных PostgreSQL'
---

import Formbricks from '@theme/MDXComponents/Formbricks'

# Миграция баз данных PostgreSQL в облачные базы данных PostgreSQL

Вы можете перенести данные из своей базы данных PostgreSQL в [облачные базы данных](https://selectel.ru/services/cloud/managed-databases/) Selectel с помощью [логической репликации](#logical-replication) или с помощью [логического дампа](#logical-dump).

:::info

Перед миграцией [создайте принимающий кластер баз данных](/managed-databases/postgresql/create-cluster.mdx) PostgreSQL с версией не ниже, чем у исходного кластера. Если вы выбрали способ миграции с помощью логического дампа, то версии кластеров должны совпадать.

:::

## Логическая репликация \{#logical-replication}

В [логической репликации](https://www.postgresql.org/docs/current/logical-replication.html) используется модель публикаций и подписок с одним или несколькими подписчиками. Они подписываются на одну или несколько публикаций на публикующем узле. На внешнем исходном кластере PostgreSQL создается публикация, на которую подписывается принимающий кластер облачных баз данных.

1. [Подготовьте исходный кластер](#prepare-source-cluster).
2. [Перенесите схему базы данных](#move-database-schema).
3. [Создайте публикацию на исходном кластере](#create-publication-on-source-cluster).
4. [Создайте подписку на принимающем кластере](#create-subscription-on-target-cluster).

### 1. Подготовить исходный кластер \{#prepare-source-cluster}

1. Добавьте пользователю с доступом к реплицируемым данным привилегию replication:

   ```sql
   ALTER ROLE <user_name> WITH REPLICATION;
   ```

   Укажите `<user_name>` — имя пользователя.

2. В файле postgresql.conf установите для уровня логирования ([Write Ahead Log](https://www.postgresql.org/docs/current/static/wal-intro.html)) значение logical:

   ```bash
   wal_level = logical
   ```

3. В файле pg\_hba.conf настройте аутентификацию:

   ```bash
   host         all            all             <host>      md5
   host         replication    all             <host>      md5
   ```

   Укажите `<host>` — IP-адрес или DNS-имя мастер-хоста принимающего кластера.

4. Перезапустите PostgreSQL для применения изменений:

   ```bash
   systemctl restart postgresql
   ```

### 2. Перенести схему базы данных \{#move-database-schema}

На исходном и принимающем кластере должна быть одинаковая схема базы данных.

1. Создайте дамп схемы на исходном кластере с помощью утилиты [pg\_dump](https://www.postgresql.org/docs/current/app-pgdump.html):

   ```bash
   pg_dump \
     -h <host> \
     -p <port> \
     -d <database_name> \
     -U <user_name> \
     --schema-only \
     --no-privileges \
     --no-subscriptions \
     --no-publications \
     -Fd -f <dump_directory>
   ```

   Укажите:

   * `<host>` — IP-адрес или DNS-имя мастер-хоста исходного кластера;
   * `<port>` — порт;
   * `<database_name>` — имя базы данных;
   * `<user_name>` — имя пользователя базы данных;
   * `<dump_directory>` — путь до дампа.

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

   ```bash
   pg_restore \
      -Fd -v \
      --single-transaction -s \
      --no-privileges \
      -O \
      -h <host> \
      -U <user_name> \
      -p <port> \
      -d <database_name> \
      <dump_directory>
   ```

   Укажите:

   * `<host>` — IP-адрес или DNS-имя хоста принимающего кластера;
   * `<user_name>` — имя пользователя базы данных;
   * `<port>` — порт;
   * `<database_name>` — имя базы данных;
   * `<dump_directory>` — путь до дампа.

### 3. Создать публикацию на исходном кластере \{#create-publication-on-source-cluster}

Для создания публикации сразу для всех таблиц нужны [права суперпользователя](https://www.postgresql.org/docs/current/sql-createpublication.html).

Создайте публикацию для таблиц, которые вы хотите перенести:

```sql
CREATE PUBLICATION <publication_name> FOR ALL TABLES;
```

Укажите `<publication_name>` — имя публикации.

### 4. Создать подписку на принимающем кластере \{#create-subscription-on-target-cluster}

В принимающем кластере облачных баз данных подписки может использовать только пользователь с ролью dbaas\_admin.

1. Создайте подписку от имени пользователя с ролью dbaas\_admin:

   ```sql
   CREATE SUBSCRIPTION <subscription_name> CONNECTION
      'host=<host>
      port=<port>
      dbname=<database_name>
      user=<user_name>
      password=<password>
      sslmode=verify-ca'
      PUBLICATION <publication_name>;
   ```

   Укажите:

   * `<subscription_name>` — имя подписки;
   * `<host>` — IP-адрес или DNS-имя мастер-хоста исходного кластера;
   * `<port>` — порт;
   * `<user_name>` — имя пользователя базы данных;
   * `<password>` — пароль пользователя;
   * `<database_name>` — имя базы данных;
   * `<publication_name>` — имя публикации.

2. Вы можете следить за статусом репликации с помощью каталога [pg\_subscription\_rel](https://www.postgresql.org/docs/current/catalog-pg-subscription-rel.html):

   ```sql
   SELECT * FROM pg_subscription_rel;
   ```

   Общее состояние репликации вы можете увидеть в представлениях pg\_stat\_subscription и pg\_stat\_replication для подписок и публикаций соответственно.

3. Последовательности (sequences) не реплицируются, поэтому перед переносом нагрузки на принимающий кластер восстановите на нем дамп с sequences, если они используются. Также перед переносом нагрузки удалите подписку в принимающем кластере:

   ```sql
   DROP SUBSCRIPTION <subscription_name>;
   ```

   Укажите `<subscription_name>` — имя подписки.

## Логический дамп \{#logical-dump}

Создайте дамп (файл с командами для восстановления) базы данных в исходном кластере и восстановите дамп в принимающем кластере.

Вы можете создать [SQL-дамп](#sql-dump) всех баз данных (сохранятся имя, таблицы, индексы и внешние ключи) или [дамп в кастомном формате](#custom-dump) (например, можно восстановить только схему или данные специфичной таблицы).

:::info

Если вы используете порт PgBouncer 5433, [измените режим пулинга](/managed-databases/postgresql/connection-pooler.mdx) PgBouncer на session. Если для PgBouncer будет включен другой режим пулинга, могут измениться search\_path для части соединений, и таблицы будут недоступны по неполному имени.

:::

### SQL-дамп \{#sql-dump}

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

   ```bash
   pg_dump \
      -h <host> \
      -U <user_name> \
      -d <database_name> \
      -f dump.sql
   ```

   Укажите:

   * `<host>` — IP-адрес или DNS-имя мастер-хоста исходного кластера;
   * `<user_name>` — имя пользователя;
   * `<database_name>` — имя базы данных.
2. Восстановите дамп в принимающем кластере с помощью утилиты [psql](https://www.postgresql.org/docs/9.3/app-psql.html):

   ```bash
   psql \
      -f dump.sql \
      -h <host> \
      -p <port> \
      -U <user_name> \
      -d <database_name>
   ```

   Укажите:

   * `<host>` — IP-адрес или DNS-имя мастер-хоста принимающего кластера;
   * `<port>` — порт;
   * `<user_name>` — имя пользователя базы данных;
   * `<database_name>` — имя базы данных.

### Кастомный дамп \{#custom-dump}

Копия базы данных в кастомном формате по умолчанию сжимается.

1. Создайте дамп базы данных в исходном кластере с помощью утилиты pg\_dump:

   ```bash
   pg_dump \
      -Fc -v \
      -h <host> \
      -U <user_name> \
      <database_name> > archive.dump
   ```

   Укажите:

   * `<host>` — IP-адрес или DNS-имя мастер-хоста исходного кластера;
   * `<user_name>` — имя пользователя базы данных;
   * `<database_name>` — имя базы данных.
2. Восстановите дамп в принимающем кластере с помощью утилиты [pg\_restore](https://www.postgresql.org/docs/13/app-pgrestore.html):

   ```bash
   pg_restore \
      -v \
      -h <host> \
      -U <user_name> \
      -d <database_name> archive.dump
   ```

   Укажите:

   * `<host>` — IP-адрес или DNS-имя мастер-хоста принимающего кластера;
   * `<user_name>` — имя пользователя базы данных;
   * `<database_name>` — имя базы данных.

<Formbricks />
