[Документация Yandex Cloud](../../../../index.md) > [Yandex Data Transfer](../../../index.md) > [Пошаговые инструкции](../../index.md) > [Настройка эндпоинтов](../index.md) > PostgreSQL > Приемник

# Передача данных в эндпоинт-приемник PostgreSQL

С помощью сервиса Yandex Data Transfer вы можете переносить данные в базу PostgreSQL и реализовывать различные сценарии переноса, обработки и трансформации данных. Для реализации трансфера:

1. [Ознакомьтесь с возможными сценариями передачи данных](#scenarios).
1. [Настройте один из поддерживаемых источников данных](#supported-sources).
1. [Подготовьте базу данных PostgreSQL](#prepare) к трансферу.
1. [Настройте эндпоинт-приемник](#endpoint-settings) в Yandex Data Transfer.
1. [Создайте](../../transfer.md#create) и [запустите](../../transfer.md#activate) трансфер.
1. [Выполняйте необходимые действия по работе с базой](#db-actions) и [контролируйте трансфер](../../monitoring.md).
1. При возникновении проблем, [воспользуйтесь готовыми решениями](#troubleshooting) по их устранению.

## Сценарии передачи данных в PostgreSQL {#scenarios}

1. Миграция — перенос данных из одного хранилища в другое. Часто это перенос базы из устаревших локальных баз в управляемые облачные.

    * [Миграция кластера PostgreSQL](../../../tutorials/managed-postgresql.md);
    * [Миграция из AWS RDS for PostgreSQL](../../../tutorials/rds-to-mpg.md);
    * [Миграция со сменой хранилища: MySQL® в PostgreSQL](../../../tutorials/mmy-to-mpg.md).

1. Поставка данных — процесс доставки произвольных данных в целевые хранилища. Процесс поставки включает извлечение данных из очереди и их десериализацию с последующей трансформацией данных в формат целевого хранилища.

    * [Поставка данных из Apache Kafka® в PostgreSQL](../../../tutorials/mkf-to-mpg.md).

1. Загрузка данных в витрины — процесс трансфера подготовленных данных в хранилища с целью последующей визуализации.

    * [Загрузка данных из Greenplum® в PostgreSQL](../../../tutorials/greenplum-to-postgresql.md);
    * [Загрузка данных из Object Storage в PostgreSQL](../../../tutorials/object-storage-to-postgresql.md).

Подробное описание возможных сценариев передачи данных в Yandex Data Transfer читайте в разделе [Практические руководства](../../../tutorials/index.md).

## Настройка источника данных {#supported-sources}

Настройте один из поддерживаемых источников данных:

* [PostgreSQL](../source/postgresql.md)
* [MySQL®](../source/mysql.md)
* [Greenplum®](../source/greenplum.md)
* [Apache Kafka®](../source/kafka.md)
* [Airbyte®](../../../transfer-matrix.md#airbyte)
* [YDS](../source/data-streams.md)
* [Yandex Object Storage](../source/object-storage.md)
* [YTsaurus](../source/yt.md)
* [Oracle](../source/oracle.md)

Полный список поддерживаемых источников и приемников в Yandex Data Transfer читайте в разделе [Доступные трансферы](../../../transfer-matrix.md).

## Подготовка базы данных приемника {#prepare}

{% list tabs %}

- Managed Service for PostgreSQL
    
    1. Убедитесь, что мажорная версия PostgreSQL на приемнике не ниже версии на источнике.
     
    1. При трансфере из PostgreSQL [включите те же расширения](../../../../managed-postgresql/operations/extensions/cluster-extensions.md) в базе приемника, что и в базе источника.

        Если в базе источника расширения установлены в пользовательскую схему, и эти расширения используются в DDL переносимых объектов, то вручную создайте в приемнике DDL. В этих DDL обращение к функции должно быть без указания схемы. В политике очистки эндпоинта-приемника установите значение `Truncate`, чтобы трансфер не удалил эти объекты.

    1. Выберите политику очистки таблиц трансфера `Drop`.

        Если вы вручную создали в приемнике DDL, используйте политику `Truncate`. При политике `Truncate` эти DDL не будут удалены.

    1. [Создайте пользователя](../../../../managed-postgresql/operations/cluster-users.md#adduser) с доступом к базе приемника.
    
    1. Выдайте созданному пользователю все привилегии на базу данных, схемы и переносимые таблицы:
    
        ```sql
        GRANT ALL PRIVILEGES ON DATABASE <имя_базы> TO <имя_пользователя>;
        ```
    
       Если база не пустая, то пользователь должен быть ее владельцем (owner):
    
        ```sql
        ALTER DATABASE <имя_базы> OWNER TO <имя_пользователя>;
        ```
    
       После старта трансфер подключится к приемнику от имени этого пользователя.
    1. Если в приемнике включена опция [сохранение границ транзакций](postgresql.md#additional-settings), выдайте созданному пользователю все привилегии на создание служебной таблицы `__data_transfer_lsn` в [текущей схеме](https://www.postgresql.org/docs/current/ddl-schemas.html#DDL-SCHEMAS-PATH) (обычно `public`) на приемнике:
    
       ```sql
       GRANT ALL PRIVILEGES ON SCHEMA <имя_схемы> TO <имя_пользователя>;
       ```

    1. Настройте [количество подключений пользователя](../../../concepts/work-with-endpoints.md#postgresql-connection-limit) к базе данных.

- PostgreSQL
    
    1. Если вы не планируете использовать для подключения к внешнему кластеру [сервис Cloud Interconnect](../../../../interconnect/concepts/index.md) или [VPN](../../../../glossary/vpn.md), разрешите подключения к такому кластеру из интернета с [IP-адресов, используемых сервисом Data Transfer](../../../../overview/concepts/public-ips.md#virtual-private-cloud).
       
       Подробнее о настройке сети для работы с внешними ресурсами читайте в [концепции](../../../concepts/network.md#source-external).
    
    1. Убедитесь, что мажорная версия PostgreSQL на приемнике не ниже версии на источнике.
    
    1. Включите те же расширения в базе приемника, что и в базе источника.
    
    1. Убедитесь, что на приемнике выбрана политика очистки `DROP таблиц трансфера`.
    
    1. Создайте пользователя:
    
        ```sql
        CREATE ROLE <имя_пользователя> LOGIN ENCRYPTED PASSWORD '<пароль>';
        ```
    
    1. Выдайте созданному пользователю все привилегии на базу данных, схемы и переносимые таблицы:
    
        ```sql
        GRANT ALL PRIVILEGES ON DATABASE <имя_базы> TO <имя_пользователя>;
        ```
    
       Если база не пустая, то пользователь должен быть ее владельцем (owner):
    
        ```sql
        ALTER DATABASE <имя_базы> OWNER TO <имя_пользователя>;
        ```
    
       После старта трансфер подключится к приемнику от имени этого пользователя.
    
    1. Если в приемнике включена опция [сохранение границ транзакций](postgresql.md#additional-settings), выдайте созданному пользователю все привилегии на создание служебной таблицы `__data_transfer_lsn` в [текущей схеме](https://www.postgresql.org/docs/current/ddl-schemas.html#DDL-SCHEMAS-PATH) (обычно `public`) на приемнике:
    
        ```sql
        GRANT ALL PRIVILEGES ON SCHEMA <имя_схемы> TO <имя_пользователя>;
        ```

    1. Настройте [количество подключений пользователя](../../../concepts/work-with-endpoints.md#postgresql-connection-limit) к базе данных.

{% endlist %}

Данные, хранящиеся в `MATERIALIZED VIEW`, не переносятся. Для переноса данных из `MATERIALIZED VIEW` создайте обыкновенный `VIEW`, ссылающийся на переносимый `MATERIALIZED VIEW`.

Если определение переносимого `VIEW` содержит вызов `VOLATILE` [функции](https://www.postgresql.org/docs/current/xfunc-volatility.html), то трансфер читает данные из такого `VIEW` с уровнем изоляции `READ UNCOMMITTED`. Консистентность между данными в этом `VIEW` и данными других переносимых объектов не гарантируется. Чтение из `MATERIALIZED VIEW` в определении `VIEW` равносильно вызову `VOLATILE` функции.

## Настройка эндпоинта-приемника PostgreSQL {#endpoint-settings}

При [создании](../index.md#create) или [изменении](../index.md#update) эндпоинта вы можете задать:

* Настройки подключения к [кластеру Yandex Managed Service for PostgreSQL](#managed-service) или [пользовательской инсталляции](#on-premise), в т. ч. на базе виртуальных машин Yandex Compute Cloud. Эти параметры обязательные.
* [Дополнительные параметры](#additional-settings).

### Кластер Managed Service for PostgreSQL {#managed-service}


{% note warning %}

Для создания или редактирования эндпоинта управляемой базы данных вам потребуется [роль `managed-postgresql.viewer`](../../../../managed-postgresql/security/index.md#mpg-viewer) или примитивная [роль `viewer`](../../../../iam/roles-reference.md#viewer), выданная на каталог кластера этой управляемой базы данных.

{% endnote %}


Подключение к БД с указанием кластера в Yandex Cloud.

{% list tabs group=instructions %}

- Консоль управления {#console}

    * **Тип подключения** — выберите вариант подключения к базе данных:
    
        * **Ручная настройка** — позволяет задать настройки подключения вручную.
    
            Выберите тип инсталляции **Кластер Managed Service for PostgreSQL** и задайте настройки:
    
            * **Кластер управляемой БД** — выберите кластер, к которому необходимо подключиться.
            * **База данных** — укажите имя базы данных в выбранном кластере.
            * **Пользователь** — укажите имя пользователя, под которым сервис Data Transfer будет подключаться к базе данных.
            * **Пароль** — укажите пароль пользователя для доступа к базе данных.
    
        * **Connection Manager** — позволяет использовать управляемое подключение к базе данных через [Yandex Connection Manager](../../../../metadata-hub/quickstart/connection-manager.md):
    
            * Выберите каталог, в котором находится кластер Managed Service for PostgreSQL.
            * Выберите тип инсталляции **Кластер управляемой БД** и задайте настройки:
    
                * **Кластер управляемой БД** — выберите кластер, к которому необходимо подключиться.
                * **Подключение** — укажите идентификатор управляемого подключения в Connection Manager.
                * **База данных** — укажите имя базы данных в выбранном кластере.
    
            {% note warning %}
            
            Чтобы использовать подключение из Connection Manager, у пользователя должны быть [права доступа](../../../../metadata-hub/operations/connection-access.md) не ниже `connection-manager.user` к этому подключению.
            
            {% endnote %}
    
    * **Группы безопасности** — выберите облачную сеть для размещения эндпоинта и группы безопасности для сетевого трафика.
      
      Это позволит применить к ВМ и кластерам в выбранной сети указанные правила групп безопасности без изменения настроек этих ВМ и кластеров. Подробнее читайте в разделе [Сеть в Yandex Data Transfer](../../../concepts/network.md).

- CLI {#cli}

    * Тип эндпоинта — `postgres-target`.

    * `--cluster-id` — идентификатор кластера, к которому необходимо подключиться.
    * `--database` — имя базы данных.
    * `--user` — имя пользователя, под которым сервис Data Transfer будет подключаться к базе данных.
    
    * Чтобы задать пароль пользователя для доступа к базе данных, используйте один из параметров:
    
        * `--raw-password` — пароль в текстовом виде.
        * `--password-file` — путь к файлу с паролем.
    
- Terraform {#tf}

    * Тип эндпоинта — `postgres_target`.

    * `security_groups` — [группы безопасности](../../../../vpc/concepts/security-groups.md) для сетевого трафика. 
      
      Правила групп безопасности применяются к трансферу. Они позволяют открыть сетевой доступ с ВМ трансфера к кластеру. Подробнее читайте в разделе [Сеть в Yandex Data Transfer](../../../concepts/network.md).
      
      Группы безопасности должны принадлежать той же сети, в которой размещен кластер.
      
      {% note info %}
      
      В Terraform сеть для групп безопасности задавать не нужно.
      
      {% endnote %}
    * `connection.mdb_cluster_id` — идентификатор кластера, к которому необходимо подключиться.
    * `database` — имя базы данных.
    * `user` — имя пользователя, под которым сервис Data Transfer будет подключаться к базе данных.
    * `password.raw` — пароль в текстовом виде.

    Пример структуры конфигурационного файла:

    
    ```hcl
    resource "yandex_datatransfer_endpoint" "<имя_эндпоинта_в_Terraform>" {
      name = "<имя_эндпоинта>"
      settings {
        postgres_target {
          security_groups = ["<список_идентификаторов_групп_безопасности>"]
          connection {
            mdb_cluster_id = "<идентификатор_кластера>"
          }
          database = "<имя_переносимой_базы_данных>"
          user     = "<имя_пользователя_для_подключения>"
          password {
            raw = "<пароль_пользователя>"
          }
        }
      }
    }
    ```


    Подробнее в [документации провайдера Terraform](../../../../terraform/resources/datatransfer_endpoint.md).

- API {#api}

    * `securityGroups` — группы безопасности для сетевого трафика, правила которых применятся к ВМ и кластерам без изменения их настроек. Подробнее читайте в разделе [Сеть в Yandex Data Transfer](../../../concepts/network.md).
    * `mdbClusterId` — идентификатор кластера, к которому необходимо подключиться.
    * `database` — имя базы данных.
    * `user` — имя пользователя, под которым сервис Data Transfer будет подключаться к базе данных.
    * `password.raw` — пароль пользователя для доступа к базе данных (в текстовом виде).

{% endlist %}

### Пользовательская инсталляция {#on-premise}

Для случая OnPremise все поля заполняются вручную.

{% list tabs group=instructions %}

- Консоль управления {#console}

    * **Тип подключения** — выберите вариант подключения к базе данных:
    
        * **Ручная настройка** — позволяет задать настройки подключения вручную.
    
            Выберите тип инсталляции **Пользовательская инсталляция** и задайте настройки:
    
            * **Хост** — укажите IP-адрес или FQDN хоста-мастера. Если на хостах открыты разные порты для подключения, то вы можете задать несколько значений хостов в формате `хост:порт`. Если вы выбираете такой формат, то значение поля **Порт** не будет учитываться.
            * **Порт** — укажите номер порта, который сервис Data Transfer будет использовать для подключения.
            * **База данных** — укажите имя базы данных в пользовательской инсталляции.
            * **Пользователь** — укажите имя пользователя, под которым сервис Data Transfer будет подключаться к базе данных.
            * **Пароль** — укажите пароль пользователя для доступа к базе данных.
            * **Сертификат CA** — загрузите файл [сертификата](../../../../managed-postgresql/operations/connect/index.md#get-ssl-cert) или добавьте его содержимое в текстовом виде, если требуется шифрование передаваемых данных, например, для соответствия требованиям PCI DSS.
              
              {% note warning %}
              
              Если не добавить сертификат, трансфер может [завершиться ошибкой](../../../troubleshooting/index.md#failed-to-connect).
              
              {% endnote %}
            * **Идентификатор подсети** — выберите или [создайте](../../../../vpc/operations/subnet-create.md) подсеть в нужной [зоне доступности](../../../../overview/concepts/geo-scope.md). Трансфер будет использовать эту подсеть для доступа к кластеру.
              
              Если значение в этом поле задано для обоих эндпоинтов, то обе подсети должны быть размещены в одной зоне доступности.
    
        * **Connection Manager** — позволяет использовать управляемое подключение к базе данных через [Yandex Connection Manager](../../../../metadata-hub/quickstart/connection-manager.md):
    
            * Выберите каталог, в котором создано управляемое подключение Connection Manager.
            * Выберите тип инсталляции **Пользовательская инсталляция** и задайте настройки:
    
                * **Подключение** — укажите идентификатор управляемого подключения в Connection Manager.
                * **База данных** — укажите имя базы данных в пользовательской инсталляции.
                * **Идентификатор подсети** — выберите или [создайте](../../../../vpc/operations/subnet-create.md) подсеть в нужной [зоне доступности](../../../../overview/concepts/geo-scope.md). Трансфер будет использовать эту подсеть для доступа к кластеру.
                  
                  Если значение в этом поле задано для обоих эндпоинтов, то обе подсети должны быть размещены в одной зоне доступности.
    
            {% note warning %}
            
            Чтобы использовать подключение из Connection Manager, у пользователя должны быть [права доступа](../../../../metadata-hub/operations/connection-access.md) не ниже `connection-manager.user` к этому подключению.
            
            {% endnote %}
    
    * **Группы безопасности** — выберите облачную сеть для размещения эндпоинта и группы безопасности для сетевого трафика.
      
      Это позволит применить к ВМ и кластерам в выбранной сети указанные правила групп безопасности без изменения настроек этих ВМ и кластеров. Подробнее читайте в разделе [Сеть в Yandex Data Transfer](../../../concepts/network.md).

- CLI {#cli}

    * Тип эндпоинта — `postgres-target`.

    * `--host` — IP-адрес или FQDN хоста-мастера, к которому необходимо подключиться.
    * `--port` — номер порта, который сервис Data Transfer будет использовать для подключения.
    * `--ca-certificate` — сертификат CA, если требуется шифрование передаваемых данных, например для соответствия требованиям PCI DSS.
      
      {% note warning %}
      
      Если не добавить сертификат, трансфер может [завершиться ошибкой](../../../troubleshooting/index.md#failed-to-connect).
      
      {% endnote %}
    * `--subnet-id` — идентификатор подсети, в которой находится хост. Трансфер будет использовать эту подсеть для доступа к хосту.
    * `--database` — имя базы данных.
    * `--user` — имя пользователя, под которым сервис Data Transfer будет подключаться к базе данных.
    
    * Чтобы задать пароль пользователя для доступа к базе данных, используйте один из параметров:
    
        * `--raw-password` — пароль в текстовом виде.
        * `--password-file` — путь к файлу с паролем.

- Terraform {#tf}

    * Тип эндпоинта — `postgres_target`.

    * `security_groups` — [группы безопасности](../../../../vpc/concepts/security-groups.md) для сетевого трафика.
      
      Правила групп безопасности применяются к трансферу. Они позволяют открыть сетевой доступ с ВМ трансфера к ВМ с базой данных. Подробнее читайте в разделе [Сеть в Yandex Data Transfer](../../../concepts/network.md).
      
      Группы безопасности должны принадлежать той же сети, что и подсеть `subnet_id`, если она указана.
      
      {% note info %}
      
      В Terraform сеть для групп безопасности задавать не нужно.
      
      {% endnote %}
    * `on_premise.hosts` — список IP-адресов или FQDN хостов, к которым необходимо подключиться. Так как поддерживается только список из одного элемента, укажите адрес хоста-мастера.
    * `on_premise.port` — номер порта, который сервис Data Transfer будет использовать для подключения.
    * `on_premise.tls_mode.enabled.ca_certificate` — сертификат CA, если требуется шифрование передаваемых данных, например для соответствия требованиям PCI DSS.
      
      {% note warning %}
      
      Если не добавить сертификат, трансфер может [завершиться ошибкой](../../../troubleshooting/index.md#failed-to-connect).
      
      {% endnote %}
    * `on_premise.subnet_id` — идентификатор [подсети](../../../../vpc/concepts/network.md#subnet), в которой находится хост. Трансфер будет использовать эту подсеть для доступа к хосту.
    * `database` — имя базы данных.
    * `user` — имя пользователя, под которым сервис Data Transfer будет подключаться к базе данных.
    * `password.raw` — пароль в текстовом виде.

    Пример структуры конфигурационного файла:

    
    ```hcl
    resource "yandex_datatransfer_endpoint" "<имя_эндпоинта_в_Terraform>" {
      name = "<имя_эндпоинта>"
      settings {
        postgres_target {
          security_groups = ["<список_идентификаторов_групп_безопасности>"]
          connection {
            on_premise {
              hosts = ["<список_хостов>"]
              port  = <порт_для_подключения>
            }
          }
          database = "<имя_переносимой_базы_данных>"
          user     = "<имя_пользователя_для_подключения>"
          password {
            raw = "<пароль_пользователя>"
          }
        }
      }
    }
    ```


    Подробнее в [документации провайдера Terraform](../../../../terraform/resources/datatransfer_endpoint.md).

- API {#api}

    * `onPremise` — параметры подключения к базе данных:
        * `hosts` — IP-адрес или FQDN хоста-мастера, к которому необходимо подключиться.
        * `port` — номер порта, который сервис Data Transfer будет использовать для подключения.
        * `tlsMode` — параметры шифрования передаваемых данных, если оно требуется, например для соответствия требованиям PCI DSS.
            * `disabled` — отключено.
            * `enabled` — включено
                * `caCertificate` — сертификат CA.
          
                  {% note warning %}
                  
                  Если не добавить сертификат, трансфер может [завершиться ошибкой](../../../troubleshooting/index.md#failed-to-connect).
                  
                  {% endnote %}
        * `subnetId` — идентификатор подсети, в которой находится хост. Трансфер будет использовать эту подсеть для доступа к хосту.
    * `securityGroups` — группы безопасности для сетевого трафика, правила которых применятся к ВМ и кластерам без изменения их настроек. Подробнее читайте в разделе [Сеть в Yandex Data Transfer](../../../concepts/network.md).
    * `database` — имя базы данных.
    * `user` — имя пользователя, под которым сервис Data Transfer будет подключаться к базе данных.
    * `password.raw` — пароль пользователя для доступа к базе данных (в текстовом виде).

{% endlist %}

### Дополнительные настройки {#additional-settings}

{% list tabs group=instructions %}

- Консоль управления {#console}

    * **Политика очистки** — выберите способ очистки данных в базе-приемнике перед переносом:
      
      * `Не очищать` — выберите эту опцию, если будет производиться только репликация без копирования данных.
      
      * `Drop` — полное удаление таблиц, участвующих в трансфере (вариант по умолчанию).
      
          Используйте эту опцию, чтобы при любой активации трансфера в базу-приемник всегда передавалась самая последняя версия схемы таблиц из источника.
      
      * `Truncate` — удалить только данные из таблиц, участвующих в трансфере, но оставить схему.
      
          Используйте эту опцию, если схема в базе-приемнике отличается от той, которая была бы перенесена из источника при трансфере.

    * **Сохранение границ транзакций** — включите, чтобы сервис записывал данные в базу-приемник только после полного чтения данных транзакции из базы-источника.
      
      Рекомендуется включать настройку при трансфере из PostgreSQL в PostgreSQL. Это может немного снизить производительность трансфера, но позволит избежать [ошибок](postgresql.md#duplicate-key), связанных с нарушением ограничений.
      
      
      {% note warning %}
      
      Эта функциональность находится на стадии [Preview](../../../../overview/concepts/launch-stages.md).
      
      {% endnote %}
  
    * **Не применять изменения схемы** — выберите, чтобы не изменять схему данных на приемнике при изменении ее на источнике. По умолчанию при изменении схемы на источнике трансфер будет автоматически применять изменения схемы в приемнике: создавать новые таблицы, добавлять новые колонки, добавлять новые перечисляемые значения и перечисляемые типы. По умолчанию не применяются такие изменения, как удаление таблиц или колонок.

- Terraform {#tf}

    * `cleanup_policy` — способ очистки данных в базе-приемнике перед переносом:
      
      * `DISABLED` — не очищать (вариант по умолчанию).
      
          Выберите эту опцию, если будет производиться только репликация без копирования данных.
      
      * `DROP` — полное удаление таблиц, участвующих в трансфере.
      
          Используйте эту опцию, чтобы при любой активации трансфера в базу-приемник всегда передавалась самая последняя версия схемы таблиц из источника.
      
      * `TRUNCATE` — удалить только данные из таблиц, участвующих в трансфере, но оставить схему.
      
          Используйте эту опцию, если схема в базе-приемнике отличается от той, которая была бы перенесена из источника при трансфере.

    * `is_schema_migration_disabled` — установите значение `true`, чтобы не изменять схему данных на приемнике при изменении ее на источнике. По умолчанию при изменении схемы на источнике трансфер будет автоматически применять изменения схемы в приемнике: создавать новые таблицы, добавлять новые колонки, добавлять новые перечисляемые значения и перечисляемые типы. По умолчанию не применяются такие изменения, как удаление таблиц или колонок.

- API {#api}

    `cleanupPolicy` — способ очистки данных в базе-приемнике перед переносом:
    
    * `DISABLED` — не очищать (вариант по умолчанию).
    
        Выберите эту опцию, если будет производиться только репликация без копирования данных.
    
    * `DROP` — полное удаление таблиц, участвующих в трансфере.
    
        Используйте эту опцию, чтобы при любой активации трансфера в базу-приемник всегда передавалась самая последняя версия схемы таблиц из источника.
    
    * `TRUNCATE` — удалить только данные из таблиц, участвующих в трансфере, но оставить схему.
    
        Используйте эту опцию, если схема в базе-приемнике отличается от той, которая была бы перенесена из источника при трансфере.

{% endlist %}

После настройки источника и приемника данных [создайте и запустите трансфер](../../transfer.md#create).

## Действия с базой данных во время трансфера {#db-actions}

{% note tip %}

Протокол репликации PostgreSQL не поддерживает передачу изменения схемы данных. Избегайте изменения схемы данных в базах источника и приемника во время трансфера. Если избежать этого невозможно, проведите явные проверки на приемнике.

{% endnote %}

Для трансферов типа _**Копирование**_ и _**Копирование и репликация**_:

* в статусе **Копируется** запрещено изменять схему данных на источнике и приемнике;
* в статусе **Реплицируется** любые изменения схемы данных на источнике вручную примените на приемнике, иначе трансфер не сможет продолжить работу.

  Например, пусть в таблицу `test_table` источника добавили новый столбец:

    ```sql
    ALTER TABLE test_table ADD COLUMN val2 TEXT;
    ```

  Если запись в эту таблицу продолжается, трансфер не сможет выполнить вставку данных на приемнике. Чтобы репликация продолжилась, выполните аналогичный запрос на изменение схемы данных на приемнике:

    ```sql
    ALTER TABLE test_table ADD COLUMN val2 TEXT;
    ```

  После этого трансфер сможет продолжить работу.

## Решение проблем, возникающих при переносе данных {#troubleshooting}

Известные проблемы, связанные с использованием эндпоинта PostgreSQL:

* [Остановка сессии мастер-транзакции трансфера](#master-trans-stop)
* [Превышение квоты на длительность соединения](#conn-duration-quota)
* [Ошибка трансфера при переносе представлений (VIEW)](#view)
* [Ошибка добавления записи в таблицу по constraint](#constraint)
* [Ошибка при переносе всех таблиц схемы](#schema)
* [Невозможно создать объекты с участием функций расширения](#extension-functions)
* [Низкая скорость трансфера](#low-speed)
* [Не переносятся таблицы-наследники](#successor-tables)
* [Не хватает слотов репликации в базе данных источника](#replication-slots)
* [Перестали переноситься данные после изменения эндпоинта-источника](#no-data-transfer)
* [Ошибка трансфера при смене хоста-мастера](#master-change)
* [Не хватает истории в WAL для продолжения репликации при смене хоста-мастера](#no-wal-story)
* [Ошибка при трансфере вложенных транзакций](#inner-tables)
* [Ошибка трансфера таблиц с отложенными ограничениями](#deferrable-constr)
* [Не удается создать слот репликации на стадии активации](#lock-replication)
* [Чрезмерное увеличение журнала WAL](#excessive-wal)
* [Ошибка при репликации из внешнего источника](#external-replication)
* [Ошибка трансфера при переносе таблиц без первичных ключей](#primary-keys)
* [Повторяющееся значение ключа нарушает уникальное ограничение](#duplicate-key)
* [Ошибка удаления таблицы при политике очистки Drop](#drop-table-error)
* [Ошибка при переносе таблиц с генерируемыми столбцами](#generated-columns)

Смотрите полный список рекомендаций в разделе [Решение проблем](../../../troubleshooting/index.md).

### Остановка сессии мастер-транзакции трансфера {#master-trans-stop}

Текст ошибки:

```text
Cannot set transaction snapshot:
ERROR: invalid snapshot identifier: "<идентификатор_снапшота>" (SQLSTATE 22023).
```

Возможные причины:

* На источнике работает cron-задание или другое приложение, которое периодически завершает слишком длительные сессии.
* Кто-то вручную завершил мастер-транзакцию.
* Ресурсов CPU на источнике не хватает для выполнения запроса.
* В настройке кластера PostgreSQL [Session duration timeout](../../../../managed-postgresql/concepts/settings-list.md#setting-session-duration-timeout) установлено ограничение на время жизни активной сессии.

**Решение:** отключите такое cron-задание, добавьте дополнительные ресурсы для CPU на источник, а также установите значение параметра **Session duration timeout** равным `0` на время трансфера. После внесения изменений [активируйте](../../transfer.md#activate) трансфер повторно.

### Превышение квоты на длительность соединения {#conn-duration-quota}

В Yandex Managed Service for PostgreSQL существует квота на длительность соединения — 12 часов.
​
​**Решение:** если перенос базы данных требует больше времени, [измените настройку кластера](../../../../managed-postgresql/operations/update.md#change-postgresql-config) Yandex Managed Service for PostgreSQL [Session duration timeout](../../../../managed-postgresql/concepts/settings-list.md#setting-session-duration-timeout).

### Ошибка трансфера при переносе представлений (VIEW) {#view}

Текст ошибки:

```text
[ERROR] "... _view": no key columns found
```

Репликация новых данных из представлений невозможна. При трансфере PostgreSQL — PostgreSQL переносятся только те представления, которые указаны в параметре эндпоинта-источника **Фильтр таблиц** → **Список включенных таблиц**.

**Решение:** вручную исключите из трансфера все представления, записав их в [параметре эндпоинта-источника](../source/postgresql.md#additional-settings) **Фильтр таблиц** → **Список исключённых таблиц**, после чего [активируйте](../../transfer.md#activate) трансфер повторно.

### Ошибка добавления записи в таблицу по constraint {#constraint}

**Решение:** подготовьте источник в соответствии с разделом [Подготовка к трансферу](../../prepare.md#source-pg).

### Ошибка при переносе всех таблиц схемы {#schema}

Текст ошибки:

```text
Unable to apply DDL of type 'TABLE', name '<схема>'.'<таблица>', error:
ERROR: schema "<схема>" does not exist (SQLSTATE 3F000)
```

Трансфер прерывается при указании списка таблиц определенной схемы в виде `<схема>.*`. Это происходит из-за особенностей работы утилиты `pg_dump`, которая используется для переноса схемы. При указании таблиц всей схемы `<схема>.*` в [параметре эндпоинта-источника](../source/postgresql.md#additional-settings) **Фильтр таблиц** → **Список включенных таблиц** типы PostgreSQL из этой схемы не извлекаются, даже если в схеме есть таблицы, зависящие от этих типов.

**Решение:** создайте типы PostgreSQL в базе-приемнике вручную.

### Невозможно создать объекты с участием функций расширения {#extension-functions}

Текст ошибки:

```text
Unable to apply DDL of type 'TABLE', <имя_объекта>, error:
failed to push non-row item 0 of kind "pg:DDL" in batch:
Push failed: ERROR: function <имя_схемы>.<имя_функции>() does not exist 
(SQLSTATE 42883)
```

В Managed Service for PostgreSQL в базе-приемнике невозможно установить расширение в пользовательскую схему. Поэтому трансфер прерывается, если в пользовательской инсталляции Managed Service for PostgreSQL есть расширения, установленные в пользовательскую схему, и эти расширения используются в DDL переносимых объектов.

**Решение:** проверьте DDL объектов, имена которых указаны в ошибке. Если в этих объектах есть вызов функций из пользовательской схемы, вручную создайте в приемнике DDL, которые вызывают функции без указания схемы. В политике очистки эндпоинта-приемника установите значение `Truncate`, чтобы трансфер не удалил эти объекты.

### Низкая скорость трансфера  {#low-speed}

​Может возникать у трансферов типа _**Копирование**_ или _**Копирование и репликация**_ из PostgreSQL в PostgreSQL.

Возможные причины:

* Протокол записи.

    В нормальном режиме трансфер работает через быстрый протокол `copy`, но при конфликтах записи батча переходит на медленную построчную запись. Чем больше конфликтов записи, тем ниже скорость трансфера.

    **Решение:** установите в эндпоинте-приемнике тип политики очистки `Drop` и исключите другие пишущие процессы.

* Параллельность чтения таблиц.

    Параллельность доступна только для таблиц, которые содержат первичный ключ. При использовании ключа [типа `serial`](https://www.postgresql.org/docs/current/datatype-numeric.html#DATATYPE-SERIAL) части таблиц читаются по диапазонам. Другие типы ключей позволяют равномерно распределять таблицы в соответствии со специальным алгоритмом.

    **Решение:** настройте [параллельное копирование](../../../concepts/sharded.md) и [активируйте трансфер](../../transfer.md#activate) повторно.

### Не переносятся таблицы-наследники {#successor-tables}

Во время трансфера не переносятся таблицы-наследники, либо переносятся без данных, если таблица партицированная.

**Решение:** установите следующие параметры эндпоинта-источника:

1. Включите опцию **Объединить наследуемые таблицы** в расширенных настройках.
1. Укажите в поле **Список включенных таблиц** все таблицы-наследники, данные которых нужно перенести.
1. Убедитесь, что у пользователя есть доступ к таблицам-наследникам.

Для увеличения скорости трансфера при переносе таблиц-наследников настройте [параллельное копирование](../../../concepts/sharded.md).

### Не хватает слотов репликации в базе данных источника {#replication-slots}

Текст ошибки:

```text
Warn(Activate): failed to create a replication slot "<идентификатор_трансфера>" at source:
failed to create a replication slot:
failed to create a replication slot:
ERROR: all replication slots are in use
(SQLSTATE 53400)
```

**Решение:** увеличьте количество [слотов репликации](https://www.postgresql.org/docs/current/logical-replication-config.html) в базе-источнике (по умолчанию `10`).

### Перестали переноситься данные после изменения эндпоинта-источника {#no-data-transfer}

После добавления таблиц в **Список включенных таблиц** в параметрах эндпоинта-источника трансфер перезапустился и перестал переносить данные.

**Решение:**

* Создайте таблицы в базе-приемнике вручную.

    1\. Создайте в базе-приемнике новые таблицы с `Primary Key` и без `Foreign key`.
    2\. Добавьте новые таблицы в **Список включенных таблиц** в [параметрах эндпоинта-источника](../source/postgresql.md#additional-setting).
    3\. Перенесите дамп с историческими данными в базу-приемник.
    4\. При появлении в логах ошибок решите их согласно конкретной ошибке.
    5\. Если ошибок нет, но логи пусты, обратитесь в [техническую поддержку](https://kz.center.yandex.cloud/support) или к вашему аккаунт-менеджеру для снятия дампа горутин. Это может помочь восстановить репликацию без повторного запуска трансфера.

* [Деактивируйте](../../transfer.md#deactivate) и [активируйте](../../transfer.md#activate) трансфер повторно.
* [Создайте](../../transfer.md#create) отдельный трансфер типа _**Копирование**_ для новых таблиц. При этом исходный трансфер можно не деактивировать.

### Ошибка трансфера при смене хоста-мастера {#master-change}

Ошибка возникает в трансферах типа _**Репликация**_ или _**Копирование и репликация**_ из-за отсутствия нужных частей Write-Ahead Log (WAL). Это происходит, когда отставание логической репликации WAL с текущего мастера на реплику превышает доступный объем WAL на других хостах. Поэтому при переключении мастера на эту реплику слот репликации не может синхронизироваться с WAL на новом мастере.

**Решение:** увеличьте лимит в [дополнительном параметре эндпоинта-источника](../source/postgresql.md#additional-setting) **Максимальный размер WAL для слота репликации** и [активируйте](../../transfer.md#activate) трансфер повторно.

### Не хватает истории в WAL для продолжения репликации при смене хоста-мастера {#no-wal-story}

При смене хоста-мастера в кластере-источнике трансферы типа _**Репликация**_ или _**Копирование и репликация**_ могут завершиться ошибкой:

```text
ERROR: requested WAL segment pg_wal/0000000E0000022700000087 has already been removed (SQLSTATE 58P01)
```

Ошибка возникает, если хранимой в [WAL](https://www.postgresql.org/docs/current/wal-intro.html) на новом мастере истории недостаточно для продолжения репликации с того же места.

**Решение**: увеличьте в кластере-источнике значение [настройки](../../../../managed-postgresql/concepts/settings-list.md#setting-wal-keep-size) `Wal keep size`. В качестве минимального значения рекомендуется взять среднее значение из графика **Source buffer size** в [мониторинге Data Transfer](../../monitoring.md). Если на диске достаточно свободных ресурсов, укажите значение настройки с запасом.

### Ошибка при трансфере вложенных транзакций {#inner-tables}

Трансфер PostgreSQL версий ниже 14 не поддерживает перенос таблиц с примененными транзакциями, которые вложены более 1024 раз и на каждом уровне вложенности есть изменения для репликации. Количество вложенностей определяется по числу вложенных конструкций `begin; .. commit;`.

**Решение:**

* Используйте PostgreSQL версии 14 или выше.
* Исключите из трансфера транзакции с таким уровнем вложенности.

### Ошибка трансфера таблиц с отложенными ограничениями {#deferrable-constr}

Ошибка возникает в трансферах типа **Репликация** или **Копирование и репликация**, так как обновление таблиц и транзакций с отложенными (`DEFERRABLE`) ограничениями не поддерживается Data Transfer. Подробнее об отложенных ограничениях в [документации PostgreSQL](https://www.postgresql.org/docs/current/sql-set-constraints.html).

**Решение:** замените тип ограничений в таких таблицах на `IMMEDIATE` и [активируйте](../../transfer.md#activate) трансфер повторно.

### Не удается создать слот репликации на стадии активации {#lock-replication}

В начале работы трансфера создается один или несколько [слотов репликации](https://www.postgresql.org/docs/current/logicaldecoding-explanation.html#LOGICALDECODING-REPLICATION-SLOTS) в базе-источнике. При этом объекты базы блокируются. Если какой-то объект заблокирован другой транзакцией, возникнет конкурирующая блокировка, и трансфер завершится с ошибкой.

**Решение:**

1. Найдите процесс, конкурирующий за блокировки с трансфером:

   ```sql
   SELECT
     activity.pid,
     activity.usename,
     activity.query,
     blocking.pid AS blocking_id,
     blocking.query AS blocking_query
   FROM
     pg_stat_activity AS activity
     JOIN pg_stat_activity AS blocking ON blocking.pid = ANY(
       pg_blocking_pids(activity.pid)
     )
   WHERE
     activity.query like '%<идентификатор_трансфера>%';
   ```

   Идентификатор трансфера можно получить со [списком трансферов в каталоге](../../transfer.md#list).

   Ответ:

   ```text
          pid      |      usename       |      query      |         blocking_id          |    blocking_query
   ----------------+--------------------+-----------------+------------------------------+----------------------
   <PID_трансфера> | <имя_пользователя> | <текст_запроса> | <PID_блокирующей_транзакции> | <блокирующий_запрос>
   (1 row)
   ```

1. Остановите транзакцию командой:

   ```sql
   SELECT pg_terminate_backend(<PID_блокирующей_транзакции>);
   ```

1. [Активируйте трансфер](../../transfer.md#activate) повторно.

### Чрезмерное увеличение журнала WAL {#excessive-wal}

Рост журнала WAL может происходить при работе трансферов типов **Копирование и репликация** и **Репликация**. Увеличение размера WAL можно заметить по:

* увеличению занятого места на диске кластера-источника (график **Disk usage on primary**);
* увеличению объема WAL-файлов на кластере-источнике (график **Total size of WAL files**);
* росту на графиках **[Source buffer size](../../monitoring.md#publisher.consumer.log_usage_bytes)** или **[Maximum data transfer delay](../../monitoring.md#sinker.pusher.time.row_max_lag_sec)** в мониторинге Data Transfer.

**Решение:**

Действуйте в зависимости от текущей стадии трансфера:

   Стадия трансфера | Причина роста WAL | Рекомендуемое действие                                                                            
   --------|-----|---------------------------------------------------------
   Копирование | Рост WAL ожидаем.  |  Дождитесь перехода трансфера на стадию репликации.                          
   Репликация | В базе-источнике присутствуют долгие транзакции (выполняющиеся более 5 минут). Такие запросы вызывают рост журнала WAL и мешают его архивации. | Дождитесь завершения транзакции или завершите сессии самостоятельно. Найти долгие транзакции можно с помощью запроса:<br>```SELECT pid, now() - pg_stat_activity.query_start```<br>```AS duration, query, state```<br>```FROM pg_stat_activity```<br>```WHERE (now() - pg_stat_activity.query_start) > interval '5 minutes'```<br>```AND state != 'idle';```
   Репликация | На источнике наблюдается большой поток изменений, который трансфер не успевает обрабатывать. | [Проверьте](../../../metrics.md) утилизацию ресурсов трансфера. Если ресурсы утилизированы полностью, то увеличьте их, уменьшите количество потоков или разделите один трансфер на несколько трансферов. [Проверьте](../../../metrics.md) утилизацию ресурсов источника и приемника. Если ресурсы утилизированы полностью, то увеличьте их.
   Репликация | На источнике в переносимых объектах была изменена схема (добавлены или удалены поля в таблицах, изменены типы и т.п.). Данные перестали записываться в приемник из-за несоответствия схем. | Самостоятельно повторите изменения схемы на приемнике.

### Ошибка при репликации из внешнего источника {#external-replication}

Текст ошибки:

```text
[XX000] ERROR: could not connect to the publisher:
SSL error: certificate verify failed FATAL:
no pg_hba.conf entry for replication connection
from host "<IP-адрес_хоста_PostgreSQL>", user "postgres", SSL off
```

**Решение:** подготовьте источник в соответствии с разделом [Подготовка к трансферу](../../prepare.md#source-pg).

### Ошибка трансфера при переносе таблиц без первичных ключей {#primary-keys}

Текст ошибки:

```text
Primary key check failed: 14 Tables errors: Table no key columns found
```

Для типов трансфера _**Репликация**_ и _**Копирование и репликация**_ таблицы без первичных ключей не переносятся.

**Решение:** подготовьте источник в соответствии с разделом [Подготовка к трансферу](../../prepare.md).

### Повторяющееся значение ключа нарушает уникальное ограничение {#duplicate-key}

Текст ошибки:

```text
ERROR: duplicate key value violates unique constraint "<название_ограничения>" (SQLSTATE 23505)
```

Ошибка может возникнуть при репликации данных из PostgreSQL в PostgreSQL. Например, когда не все события транзакции поместились в память и в базу-приемник передана только часть строк транзакции из базы-источника. В базе-приемнике эта часть строк по умолчанию применяется в отдельной транзакции, поэтому в определенный момент времени может возникнуть нарушение ограничений, например дублирование ключа.

**Решение:** используйте один из вариантов:

* Для эндпоинта-приемника [включите расширенную настройку](postgresql.md#additional-settings) **Сохранение границ транзакций**. Data Transfer откроет транзакцию, применит пришедшие события, но выполнит коммит транзакции, только когда начнет получать данные следующей транзакции.

    Включение настройки **Сохранение границ транзакций** может немного снизить производительность трансфера, но позволит избежать ошибок, связанных с нарушением ограничений.

* Отключите в базе-приемнике ограничения. В определенный момент времени возможно нарушение ограничений (например, когда применена часть транзакции из базы-источника в базе-приемнике). Но Data Transfer гарантирует согласованность данных в итоге (eventually consistency) — когда вторая часть транзакции применится в базе-приемнике, нарушения ограничений не будет.

### Ошибка удаления таблицы при политике очистки Drop {#drop-table-error}

Текст ошибки:

```text
ERROR: cannot drop table <имя_таблицы> because other objects depend on it (SQLSTATE 2BP01)
```

При политике очистки `Drop` трансфер удаляет таблицы в несколько итераций:

1. Трансфер последовательно пытается удалить все таблицы. Каскадное удаление не используется, так как может привести к удалению таблиц, не участвующих в трансфере. Если таблицу невозможно удалить, например, из-за связанности внешними ключами, возникает ошибка, но трансфер продолжит удаление таблиц.
1. Во время следующей итерации трансфер пытается удалить оставшиеся таблицы. Если блокирующие дочерние таблицы были удалены в предыдущей итерации, таблица со связанностью внешними ключами удаляется. В этом случае ошибка устраняется в процессе работы Data Transfer, дополнительных действий не требуется.
1. Если во время очередной итерации трансфер не удалил ни одной таблицы, процесс удаления таблиц завершается. При этом:

    * Трансфер продолжит работу, если все таблицы были удалены.
    * Трансфер прервется с ошибкой, если остались неудаленные таблицы.

**Решение:**

* Если дочерние таблицы не участвуют в других трансферах и их перенос не противоречит целям трансфера, добавьте эти таблицы:

    * В список включенных таблиц в параметрах эндпоинта-источника.
    * В список объектов для переноса в параметрах трансфера.

* Удалите блокирующие дочерние таблицы в базе-приемнике вручную.
* Используйте политику очистки `Truncate`.
* Пересоздайте базу в приемнике.

    {% note warning %}

    Это приведет к потере всех данных в базе.

    {% endnote %}

### Ошибка при переносе таблиц с генерируемыми столбцами {#generated-columns}

Текст ошибки:

```text
ERROR: column "<имя_столбца>" is a generated column (SQLSTATE 42P10)
```

Ошибка может возникнуть, если из базы-источника переносится таблица, которая содержит генерируемые столбцы. Например, если генерируемый столбец определен как столбец идентификаторов (`GENERATED ... AS IDENTITY`), то ошибка возникнет при репликации данных. Если генерируемый столбец вычисляемый, то ошибка возникнет независимо от типа трансфера. Подробнее о генерируемых столбцах в [документации PostgreSQL](https://www.postgresql.org/docs/current/ddl-generated-columns.html).

**Решение**: в [параметрах эндпоинта-источника](../source/postgresql.md#additional-settings) исключите из трансфера таблицы, которые содержат генерируемые столбцы.