Уровень 2.0
В этой лекции:
- Общие сведения о расширяемости Pangolin
- Файлы расширения
- Версионность и обновление расширений
- Расширения и утилита
pg_dump
Управление расширениями
Возможности расширений
Pangolin как специальная версия PostgreSQL обладает массой возможностей по расширению своей функциональности.
Без изменения исходного кода сервера могут добавляться:
- Языки программирования
- Пользовательские функции и процедуры
- Типы данных
- Операторы для работы с типами данных
- Методы доступа к данным
- Обертки сторонних данных (FDW, Foreign Data Wrapper)
Это возможно, потому что в системном каталоге хранится большой объем метаинформации об объектах баз данных. В большинстве других реляционных СУБД, не основанных на PostgreSQL, в системном каталоге, как правило, хранится только информация об отношениях и их столбцах, что ограничивает возможности по их расширению.
Общие механизмы расширяемости
Добавление новой функциональности выполняется путем изменения содержимого таблиц системного каталога, а не исходного кода сервера.
При этом добавляемая функциональность может быть реализована либо на языке SQL, либо на других языках программирования в виде разделяемых библиотек.
Например, уже известные по курсу DBA2 расширения pageinspect и pg_buffercache реализованы в виде разделяемых библиотек.
При этом библиотека pg_buffercache загружается вместе с сервером Pangolin. Для этого она указывается в конфигурационном параметре shared_preload_libraries.
В свою очередь, ядро Pangolin предоставляет интерфейс для доступа к своим функциям посредством API.
Помимо этого, в исходном коде ядра предусмотрено достаточно большое количество мест для подстановки собственного кода (hooks, хуки), изменяющего поведение СУБД.
Например, известное расширение pg_stat_statements, накапливающее статистику выполнения запросов, использует хук ExecutorRun_hook на этапе выполнения запроса.
Расширение как объект базы данных
Расширением является набор взаимосвязанных объектов базы данных.
Список объектов, которые могут входить в состав расширения, перечислен в описании команды ALTER EXTENSION.
Связь между объектами расширения должна быть неразрывной, поэтому их создание и удаление выполняются вместе.
По этой причине для управления расширениями используется отдельный объект базы данных, для создания которого применяется команда CREATE EXTENSION. Перед созданием расширения оно должно быть установлено в системе, то есть должны быть созданы и размещены в определенных каталогах операционной системы необходимые файлы.
Механизм расширений следит за их целостностью. При попытке удаления отдельного объекта из состава расширения возникает ошибка. Однако изменение объектов в расширении все же возможно. Ответственность за это лежит на администраторе СУБД.
Удаление расширения выполняется командой DROP EXTENSION. Поведение по умолчанию указанной команды определяется опцией RESTRICT. Это означает, что при наличии в базе данных объектов, зависимых от объектов из состава расширения, а также других зависимых расширений выполнение команды завершится ошибкой.
Для удаления вместе с расширением всех зависимых объектов необходимо указать опцию CASCADE (DROP EXTENSION ... CASCADE).
Источники расширений
В состав Pangolin входит достаточно много готовых расширений.
Они находятся в каталоге contrib дистрибутива и устанавливаются вместе с сервером Pangolin. Информацию по ним можно узнать из документации.
Некоторые из предустановленных расширений уже были использованы в курсе DBA2 для исследования внутреннего устройства Pangolin (pageinspect, pg_buffercache, pg_visibility, pgstattuple, pg_walinspect, pgrowlocks).
Некоторые будут использованы в текущем курсе при решении задач резервного копирования и миграции данных (ptrack, pg_upgrade).
Обратите внимание, что процедурный язык PL/PgSQL также является расширением с именем plpgsql.
Помимо этого существуют другие источники готовых расширений. В частности, существует сеть распространения расширений PostgreSQL (PGXN, PostgreSQL Extension Network). Это открытый ресурс, позволяющий разработчикам распространять свои расширения, а пользователям их находить и использовать.
Список установленных в системе расширений может быть получен с использованием системного представления pg_available_extensions.
Файлы расширения
Для создания расширения требуется минимум два файла:
- Управляющий файл
- Файл со скриптом
Управляющий файл содержит базовые параметры расширения.
В файле со скриптом содержится набор SQL-команд для создания объектов базы данных из состава расширения.
Указанный скрипт выполняется при вызове команды CREATE EXTENSION.
Если расширение написано с использованием языка C, также требуется файл разделяемой библиотеки, содержащий скомпилированный код.
Управляющий файл
Управляющий файл должен быть назван в соответствии с шаблоном имя_расширения.control и находиться в каталоге SHAREDIR/extension, где SHAREDIR указывает на каталог с общими данными Pangolin.
Значение SHAREDIR можно узнать с использованием команды pg_config --sharedir.
В управляющем файле среди прочего могут быть заданы следующие параметры:
directory— каталог с файлами скриптов (по умолчанию каталог хранения управляющего файла)default_version— версия расширения по умолчанию — та версия, которая будет загружена командойCREATE EXTENSIONбез явного ее указанияcomment— комментарий к расширениюencoding— кодировка символов в файлах скриптов. Задается, если в файлах используются символы не из набораASCII.module_pathname— значение для подстановки вместо каждого вхожденияMODULE_PATHNAMEв скриптах.MODULE_PATHNAMEобычно используется в SQL-командахCREATE FUNCTIONдля указания имени разделяемой библиотеки на языкеCrequires— список расширений, от которых зависит данное расширениеrelocatable— допускается ли перемещение расширения между схемами (по умолчаниюfalse)
Полный список параметров управляющего файла можно узнать из документации.
Например, содержимое управляющего файла расширения pg_buffercache выглядит следующим образом:
[postgres@ServerName ~]$ cat /usr/pangolin-major.minor/share/extension/pg_buffercache.control
# pg_buffercache extension
comment = 'examine the shared buffer cache'
default_version = '1.3'
module_pathname = '$libdir/pg_buffercache'
relocatable = true
В этом случае версией по умолчанию является "1.3", значение для подстановки имени разделяемой библиотеки "$libdir/pg_buffercache", где вместо "$libdir", в свою очередь, подставляется путь к каталогу с библиотеками Pangolin.
Файл со скриптом
В файле-скрипте содержится набор SQL-команд для создания объектов базы данных из состава расширения. Указанный скрипт выполняется при вызове команды CREATE EXTENSION.
Файл должен быть назван в соответствии с шаблоном имя_расширения--имя_версии.sql и находиться либо в каталоге, указанном в параметре directory управляющего файла, либо в том же каталоге, что и управляющий файл, если значение параметра directory не задано.
Команды в скрипте неявно выполняются в рамках одной транзакции, поэтому среди них не может быть команд управления транзакциями (BEGIN, COMMIT и т.д.) и других команд, выполнение которых недопустимо внутри блока транзакций (например, VACUUM или REINDEX).
Например, содержимое скрипта расширения pg_buffercache выглядит следующим образом:
[postgres@ServerName ~]$ cat /usr/pangolin-major.minor/share/extension/pg_buffercache--1.2.sql
/* contrib/pg_buffercache/pg_buffercache--1.2.sql */
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION pg_buffercache" to load this file. \quit
-- Register the function.
CREATE FUNCTION pg_buffercache_pages()
RETURNS SETOF RECORD
AS 'MODULE_PATHNAME', 'pg_buffercache_pages'
LANGUAGE C PARALLEL SAFE;
-- Create a view for convenient access.
CREATE VIEW pg_buffercache AS
SELECT P.* FROM pg_buffercache_pages() AS P
(bufferid integer, relfilenode oid, reltablespace oid, reldatabase oid,
relforknumber int2, relblocknumber int8, isdirty bool, usagecount int2,
pinning_backends int4);
-- Don't want these to be available to public.
REVOKE ALL ON FUNCTION pg_buffercache_pages() FROM PUBLIC;
REVOKE ALL ON pg_buffercache FROM PUBLIC;
Здесь представлено содержимое скрипта для версии "1.2" расширения pg_buffercache.
В скрипте SQL-командой CREATE FUNCTION создается функция pg_buffercache_pages на языке C (LANGUAGE C), реализация которой находится в разделяемой библиотеке.
Имя разделяемой библиотеки определяется путем подстановки вместо "MODULE_PATHNAME" значения module_pathname из управляющего файла.
Также в скрипте SQL-командой CREATE VIEW создается представление pg_buffercache, основанное на использовании созданной функции pg_buffercache_pages.
Помимо этого, в скрипте есть команды для лишения привилегий на созданные функции и представление у псевдороли PUBLIC, то есть у всех ролей, кроме суперпользователя.
Также в начале скрипта имеется пара команд: \echo и \quit.
Они необходимы для исключения возможности выполнения скрипта в psql. В случае такой попытки будет выдано сообщение о необходимости использования команды CREATE EXTENSION и выполнение скрипта прекратится.
В свою очередь, механизм расширений игнорирует указанные команды.
Версионность и обновление расширений
Одним из преимуществ механизма расширения является поддержка версионности и наличие удобного способа управления обновлениями расширений.
Создание расширения заданной версии
Версия расширения определяется некоторым именем, не обязательно являющимся комбинацией чисел. Pangolin не делает предположений о порядке версий на основе их имен. Например, версия "1.1" может быть новее версии "1.2".
Создание расширения заданной версии может быть выполнено командой CREATE EXTENSION VERSION, например:
postgres=# CREATE EXTENSION pg_buffercache VERSION '1.2';
При этом для устанавливаемой версии обновления должен быть в наличии либо файл со скриптом, соответствующий устанавливаемой версии, либо файл со скриптом некоторой другой версии и цепочка файлов-скриптов обновлений с этой версии до целевой версии расширения. Цепочки скриптов обновлений более подробно рассматриваются ниже.
Обновление расширения
Установленное расширение может быть обновлено командой ALTER EXTENSION UPDATE TO, например:
postgres=# ALTER EXTENSION pg_buffercache UPDATE TO '1.3';
Без явного указания версии обновление выполняется до версии, указанной в параметре default_version управляющего файла.
Для того чтобы обновление было возможным, должна быть в наличии цепочка из файлов-скриптов обновлений, начиная с установленной версии и заканчивая целевой.
Файлы-скрипты обновлений должны находиться в каталоге с файлами-скриптами версий и называться в соответствии с шаблоном имя_расширения--имя_исходной_версии--имя_целевой_версии.sql
Например, для расширения pg_buffercache содержимое каталога с файлами скриптов выглядит следующим образом:
[postgres@ServerName ~]$ ls -1 /usr/pangolin-major.minor/share/extension/pg_buffercache*
/usr/pangolin-major.minor/share/extension/pg_buffercache--1.0--1.1.sql
/usr/pangolin-major.minor/share/extension/pg_buffercache--1.1--1.2.sql
/usr/pangolin-major.minor/share/extension/pg_buffercache--1.2--1.3.sql
/usr/pangolin-major.minor/share/extension/pg_buffercache--1.2.sql
/usr/pangolin-major.minor/share/extension/pg_buffercache.control
В данном случае обновление с версии "1.2" до версии "1.3" может быть выполнено с использованием файла pg_buffercache--1.2--1.3.sql.
Содержимое указанного файла представлено ниже:
[postgres@ServerName ~]$ cat /usr/pangolin-major.minor/share/extension/pg_buffercache--1.2--1.3.sql
/* contrib/pg_buffercache/pg_buffercache--1.2--1.3.sql */
-- complain if script is sourced in psql, rather than via ALTER EXTENSION
\echo Use "ALTER EXTENSION pg_buffercache UPDATE TO '1.3'" to load this file. \quit
GRANT EXECUTE ON FUNCTION pg_buffercache_pages() TO pg_monitor;
GRANT SELECT ON pg_buffercache TO pg_monitor;
В данном случае в файле-скрипте обновления содержатся только команды предоставления привилегий по использованию объектов расширения роли pg_monitor.
Возможность выполнения обновления с одной версии на другую можно определить с использованием функции pg_extension_update_paths, например:
postgres=# SELECT * FROM pg_extension_update_paths('pg_buffercache');
source | target | path
--------+--------+--------------------
1.0 | 1.1 | 1.0--1.1
1.0 | 1.2 | 1.0--1.1--1.2
1.0 | 1.3 | 1.0--1.1--1.2--1.3
1.1 | 1.0 |
1.1 | 1.2 | 1.1--1.2
1.1 | 1.3 | 1.1--1.2--1.3
1.2 | 1.0 |
1.2 | 1.1 |
1.2 | 1.3 | 1.2--1.3
1.3 | 1.0 |
1.3 | 1.1 |
1.3 | 1.2 |
(12 rows)
В поле path указывается цепочка скриптов обновлений, с помощью которых может быть выполнено обновление с исходной (поле source) до целевой версии (поле target).
Дополнительный управляющий файл
В случае необходимости для новой версии может быть создан дополнительный управляющий файл.
Он должен быть расположен в том же каталоге, что и основной управляющий файл, и называться в соответствии с шаблоном имя_расширения--имя_версии.control.
Дополнительный управляющий файл может потребоваться, например, если в новой версии появились новые зависимости от других расширений.
Значения параметров дополнительного управляющего файла переопределяют соответствующие значения основного управляющего файла.
Однако параметры directory и default_version в дополнительных управляющих файлах не могут быть указаны.
Расширения и утилита pg_dump
Утилита логического резервного копирования pg_dump (см. лекцию «Логическое резервное копирование») не выполняет выгрузку команд по созданию объектов из состава расширения.
Она лишь выгружает команды CREATE EXTENSION.
Такое поведение существенно упрощает миграцию базы данных на новую версию расширения, поскольку новая версия может содержать другой набор объектов базы данных.
Однако такое поведение накладывает некоторые ограничения.
Во-первых, при восстановлении из такой резервной копии необходимые файлы расширения (управлящие файлы и файлы-скрипты) должны быть в наличии в соответствующих каталогах.
Во-вторых, в составе расширения могут содержаться таблицы, данные в которых могут быть изменены пользователем после установки расширения. Соответственно, обновленные данные не будут содержаться ни в файлах-скриптах расширения, ни в выгруженной резервной копии.
Для решения данной проблемы в скрипте расширения такая таблица может быть помечена как конфигурационная. Такая пометка выполняется с использованием функции pg_extension_config_dump.
В результате этого pg_dump включит в выгружаемые данные содержимое помеченной таблицы, но не ее определение. При этом в параметрах функции pg_extension_config_dump может быть указано условие для выгрузки данных.
Например, в файле-скрипте могут содержаться следующие команды:
CREATE TABLE config_table (id integer, value integer, is_predefined boolean);
INSERT INTO config_table VALUES (1, 100, true), (2, 200, true), (3, 300, true);
SELECT pg_extension_config_dump('config_table', 'WHERE NOT is_predefined');
При создании резервной копии в этом случае pg_dump добавит команды наполнения таблицы строками, не отмеченными полем is_predefined, что позволит сохранить актуальное содержимое таблицы при переносе.
Итоги
- Pangolin обладает широкими возможностями расширяемости благодаря большому объему информации в системном каталоге
- Расширение — это группа взаимосвязанных объектов базы данных
- В Pangolin имеются удобные инструменты для обновления расширений
- Механизм расширений необходимо учитывать при использовании утилиты
pg_dump
Самопроверка
Вопрос 1
Наличие каких файлов является обязательным для создания расширения, реализованного с использованием языка C? Выберите все верные варианты ответа:
Вопрос 2
В каталоге с файлами расширения имеется файл-скрипт обновления some_extension--1.4--1.2.sql.
До какой версии будет обновлено расширение some_extension в результате выполнения команд из указанного файла?
Вопрос 3
Какие команды, касающиеся расширений, выгружаются утилитой pg_dump? Выберите все верные варианты ответа: