Глава 62. Пользовательские менеджеры ресурсов WAL

В этой главе описывается интерфейс взаимодействия ядра PostgreSQL с пользовательскими менеджерами ресурсов WAL, используя который расширения могут непосредственно интегрировать свои объекты в WAL.

Расширениям, особенно реализующим табличные методы доступа или индексные методы доступа, может потребоваться использовать WAL для восстановления, репликации и/или логического декодирования. Пользовательские менеджеры ресурсов представляют собой более гибкую альтернативу унифицированным записям WAL (которые игнорируются при логическом декодировании), но реализовать их в расширениях сложнее.

Чтобы создать новый пользовательский менеджер ресурсов WAL, сначала определите структуру RmgrData с реализациями методов менеджера ресурсов. Подробнее она описывается в src/backend/access/transam/README и в src/include/access/xlog_internal.h в исходном коде PostgreSQL.

/*
  * Таблица методов для менеджеров ресурсов.
  *
  * Эта структура должна синхронизироваться с определением PG_RMGR в
  * файле rmgr.c.
  *
  * Метод rm_identify должен выдать обозначение записи для переданного xl_info
  * (без ссылки на rmid). Например, для XLOG_BTREE_VACUUM он мог бы выдать
  * "VACUUM". Затем может быть вызван метод rm_desc, который должен выдать
  * дополнительные сведения о записи, если они имеются
  * (например, последний блок).
  *
  * Метод rm_mask принимает на вход страницу, изменённую менеджером ресурсов, и
  * маскирует биты, на изменение которых не должна реагировать проверка
  * wal_consistency_checking.
  *
  * Индексами в RmgrTable[] являются значения RmgrId (см. rmgrlist.h). Если
  * rm_name имеет значение NULL, соответствующая запись RmgrTable считается
  * недействительной.
 */
typedef struct RmgrData
{
    const char *rm_name;
    void        (*rm_redo) (XLogReaderState *record);
    void        (*rm_desc) (StringInfo buf, XLogReaderState *record);
    const char *(*rm_identify) (uint8 info);
    void        (*rm_startup) (void);
    void        (*rm_cleanup) (void);
    void        (*rm_mask) (char *pagedata, BlockNumber blkno);
    void        (*rm_decode) (struct LogicalDecodingContext *ctx,
                              struct XLogRecordBuffer *buf);
} RmgrData;

Затем зарегистрируйте новый менеджер ресурсов.

/*
  * Регистрация нового пользовательского менеджера ресурсов WAL.
  *
  * Идентификаторы менеджеров ресурсов должны быть глобально уникальными
  * среди всех расширений. Чтобы избежать конфликтов с расширениями других
  * разработчиков, зарезервируйте уникальный RmgrId для вашего расширения на
  * странице https://wiki.postgresql.org/wiki/CustomWALResourceManagers.
  * В процессе разработки следует использовать RM_EXPERIMENTAL_ID, чтобы
  * не резервировать лишние идентификаторы.
 */
extern void RegisterCustomRmgr(RmgrId rmid, RmgrData *rmgr);

Функция RegisterCustomRmgr должна вызываться из функции _PG_init модуля расширения. В процессе разработки нового расширения в качестве rmid следует использовать RM_EXPERIMENTAL_ID. Когда расширение для пользователей будет готово к выпуску, зарезервируйте новый идентификатор менеджера ресурсов на странице Custom WAL Resource Manager (Пользовательский менеджер ресурсов WAL).

Включите модуль расширения, реализующий пользовательский менеджер ресурсов, в shared_preload_libraries, чтобы он загружался при запуске PostgreSQL.

Примечание

Расширение должно оставаться в shared_preload_libraries до тех пор, пока в системе могут быть какие-либо пользовательские записи WAL. В противном случае сервер PostgreSQL не сможет применять или декодировать пользовательские записи WAL, вследствие чего он может не запуститься.