Перейти к основному содержимому

Настройка репликации DDL операций

GraDeLy поддерживает возможность репликации DDL операций.

Последовательность выполнения​

  1. В БД источнике создайте функцию вызова посылки сообщений с информацией об изменениях в слот репликации:

    CREATE OR REPLACE FUNCTION {schema}.grdl_ddl_emit()
    RETURNS event_trigger
    LANGUAGE plpgsql
    SECURITY DEFINER
    SET search_path TO 'pg_catalog'
    AS $function$
    DECLARE
    _command_text text := current_query();
    _event text := TG_EVENT;
    _tag text := 'grdl_ddl_event';
    _cmd text := TG_TAG;

    r_object_type text;
    r_schema_name text;
    r_object_name text;

    payload text;
    v_norepl text;
    BEGIN
    v_norepl := current_setting('grdl.noreplicate', true);

    IF coalesce(v_norepl, 'off') = 'on' THEN
    RETURN;
    END IF;

    IF current_setting('wal_level', true) IS DISTINCT FROM 'logical' THEN
    RETURN;
    END IF;

    IF _event = 'sql_drop' AND _cmd LIKE 'ALTER %' THEN
    RETURN;
    END IF;

    IF _event = 'sql_drop' THEN
    SELECT object_type, schema_name, object_identity
    INTO r_object_type, r_schema_name, r_object_name
    FROM pg_event_trigger_dropped_objects()
    WHERE original
    AND COALESCE(schema_name,') NOT LIKE 'pg_toast%'
    AND COALESCE(schema_name,') NOT LIKE 'pg_temp%'
    ORDER BY object_identity NULLS LAST
    LIMIT 1;
    ELSE
    SELECT object_type, schema_name, object_identity
    INTO r_object_type, r_schema_name, r_object_name
    FROM pg_event_trigger_ddl_commands()
    WHERE command_tag = _cmd
    AND COALESCE(schema_name,') NOT LIKE 'pg_toast%'
    AND COALESCE(schema_name,') NOT LIKE 'pg_temp%'
    ORDER BY object_identity NULLS LAST
    LIMIT 1;
    END IF;

    IF NOT FOUND THEN
    RETURN;
    END IF;

    IF _cmd IN ('CREATE INDEX', 'REINDEX INDEX', 'REINDEX TABLE')
    AND _command_text ILIKE '%CONCURRENTLY%' THEN
    RETURN;
    END IF;

    payload := json_build_object(
    'ObjectType', r_object_type,
    'SchemaName', r_schema_name,
    'ObjectName', r_object_name,
    'Command', _cmd,
    'CommandTag', _tag,
    'CommandText', _command_text
    )::text;

    PERFORM pg_logical_emit_message(true, _tag, payload);
    END;
    $function$
    ;
  2. В БД источнике создайте триггеры, подписанные на события ddl_command_end и sql_drop, вызывающие функцию посылки:

    CREATE EVENT TRIGGER grdl_ddl_emit_create ON ddl_command_end EXECUTE FUNCTION <schema_name>.grdl_ddl_emit();
    CREATE EVENT TRIGGER grdl_ddl_emit_drop ON sql_drop EXECUTE FUNCTION <schema_name>.grdl_ddl_emit();
  3. В БД источнике создайте публикацию с включением всех таблиц или отдельных таблиц.

примечание

При использовании публикации отдельных таблиц необходимо пересоздание или обновление публикации с добавлением новых таблиц. Правила созданий публикаций

  1. Дополнительно выдайте права репликатору на объекты приемника:

    GRANT ALL ON ALL TABLES IN SCHEMA <schema_name> TO gdl_worker
примечание

Активация репликации DDL операций на пользовательском интерфейсе выполняется при редактировании свойств модулей захвата и применения. По умолчанию функциональность выключена.

Чтобы настроить фильтрацию транзакций​

Для исключения конкретных операций из захвата, DDL запрос необходимо пометить специальным выражением до начала операции 'SET LOCAL grdl.noreplicate = 'on'' и после операции (необязательно) 'SET LOCAL grdl.noreplicate = 'off''. При наличии специального выражения DDL операция в wal-журнал не отправляется.

примечание

SET LOCAL grdl.noreplicate - работает в рамках транзакции, дополнительные права на использование не нужны.

Результат​

Настроена репликация DDL операций