Глава 61. Определение интерфейса для табличных методов доступа
В этой главе описывается интерфейс между ядром системы PostgreSQL и табличными методами доступа, которые управляют хранением таблиц. Ядро системы не знает об этих метода доступа ничего, кроме того, что описано здесь; благодаря этому можно реализовывать абсолютно новые типы методов в рамках расширений.
Каждый табличный метод доступа описывается строкой в системном каталоге pg_am
. В записи pg_am
указывается имя и функция-обработчик для этого табличного метода. Эти записи могут создаваться и удаляться командами SQL CREATE ACCESS METHOD и DROP ACCESS METHOD.
Функция-обработчик табличного метода доступа должна объявляться как принимающая один аргумент типа internal
и возвращающая псевдотип table_am_handler
. Аргумент в данном случае фиктивный и нужен только для того, чтобы эту функцию нельзя было вызывать непосредственно из команд SQL. Возвращать эта функция должна указатель на структуру типа TableAmRoutine
, содержащую всё, что нужно знать коду ядра, чтобы использовать этот метод доступа. Возвращаемое значение должно существовать всё время жизни сервера, что обычно достигается объявлением глобальной переменной static const
. Структура TableAmRoutine
, также называемая структурой API метода доступа, определяет поведение метода доступа через обработчики. Эти обработчики задаются как обычные указатели на функции уровня C, поэтому они не видны и не доступны на уровне SQL. Все обработчики и их свойства задаются в структуре TableAmRoutine
, в определении которой можно найти комментарии с требованиями к ним. Для большинства обработчиков созданы функции-обёртки, документированные с точки зрения пользователя (а не разработчика) табличного метода доступа. Более подробно это описывается в файле src/include/access/tableam.h
.
Чтобы реализовать метод доступа (МД), разработчик обычно должен создать для него специальный слот таблицы кортежей (см. src/include/executor/tuptable.h
), позволяющий коду снаружи метода доступа иметь ссылки на кортежи данного МД и обращаться к столбцам кортежа.
В настоящее время способ хранения данных, определяемый МД, может быть практически любым. Например, МД может по своему усмотрению использовать кеш общих буферов. Если этот кеш используется, скорее всего имеет смысл применять и стандартную компоновку страницы, описанную в Разделе 70.6.
Одним довольно серьёзным ограничением API табличных методов доступа является то, что в настоящее время МД может поддерживать модификации данных и/или индексы, только если для каждого кортежа имеется идентификатор (TID), состоящий из номера блока и номера элемента (см. также Раздел 70.6). Компоненты TIDs в принципе могут иметь значение, отличное от принятого для метода heap
, но если желательно поддерживать сканирование по битовой карте (вообще это не обязательно), номер блока должен обеспечивать локальность данных.
Для восстановления при сбое МД может использовать WAL сервера или собственную реализацию журнала. В случае использования WAL в МД можно задействовать Унифицированные записи WAL или реализовать свой тип записей WAL. Использовать унифицированные записи проще, но они занимают больше места в WAL. Для реализации нового типа записей WAL в настоящее время необходимо вносить изменения в код ядра (в частности, в src/include/access/rmgrlist.h
).
Чтобы реализовать поддержку транзакций способом, позволяющим обращаться к различным табличным методам в одной транзакции, скорее всего потребуется интегрировать её в механизм src/backend/access/transam/xlog.c
.
Разработчик нового табличного метода доступа
может почерпнуть другую полезную информацию из реализации существующего метода heap
, находящейся в src/backend/access/heap/heapam_handler.c
.