Расширяемость
Фоновые процессы
16
Авторские права
© Postgres Professional, 2017–2024
Авторы: Егор Рогов, Павел Лузанов, Илья Баштанов, Игорь Гнатюк
Фото: Олег Бартунов (монастырь Пху и пик Бхрикути, Непал)
Использование материалов курса
Некоммерческое использование материалов курса (презентации,
демонстрации) разрешается без ограничений. Коммерческое
использование возможно только с письменного разрешения компании
Postgres Professional. Запрещается внесение изменений в материалы
курса.
Обратная связь
Отзывы, замечания и предложения направляйте по адресу:
Отказ от ответственности
Компания Postgres Professional не несет никакой ответственности за
любые повреждения и убытки, включая потерю дохода, нанесенные
прямым или непрямым, специальным или случайным использованием
материалов курса. Компания Postgres Professional не предоставляет
каких-либо гарантий на материалы курса. Материалы курса
предоставляются на основе принципа «как есть» и компания Postgres
Professional не обязана предоставлять сопровождение, поддержку,
обновления, расширения и изменения.
2
Темы
Механизм фоновых процессов
Применение в ядре PostgreSQL
Возможности для прикладных задач
Расширение dblink
Расширение pg_background
3
Фоновые процессы
Фиксированный набор служебных процессов
postmaster
walwriter
checkpointer
autovacuum
и другие
Динамически порождаемые фоновые процессы
контролируются процессом postmaster
имеют доступ к разделяемой памяти
могут устанавливать внутреннее соединение с базами данных
реализуются на языке C
PostgreSQL состоит из набора взаимодействующих процессов.
За основными процессами закреплены собственные имена и они
имеют особый смысл для сервера. Например, при остановке
экземпляра нужно записать в журнал сообщение о завершении
контрольной точки, поэтому процесс walwriter надо останавливать
после checkpointer, и т. п. Обычно (хотя и не всегда) такие процессы
работают постоянно от старта сервера до его останова.
Но вместе с тем часто возникает необходимость временно запустить
процесс, который выполнит необходимую работу и завершится. Такую
возможность предоставляет механизм фоновых процессов
Как и все остальные, фоновые процессы порождаются и
контролируются процессом postmaster. Фоновые процессы имеют
все возможности, такие как доступ к разделяемой памяти сервера
и соединение с базами данных по внутреннему протоколу SPI
(рассматривается в теме «Языки программирования»).
Фоновые процессы должны быть написаны на языке C, пример можно
найти в исходном коде (src/test/modules/worker_spi).
Заметим, что процесс автоочистки (autovacuum launcher) тоже
динамически порождает рабочие процессы (autovacuum worker),
но исторически делает это по-своему, не используя общий механизм
фоновых процессов.
4
Использование
Параллельное выполнение запросов
max_parallel_workers = 8
Параллельное выполнение служебных команд
max_parallel_maintenance_workers = 2
Логическая репликация
max_logical_replication_workers = 4
max_worker_processe s = 8
Фоновые процессы используются в PostgreSQL для различных целей.
1. Параллельное выполнение запросов.
2. Параллельное выполнение служебных команд (CREATE INDEX
и REINDEX (в т. ч. CONCURRENTLY) для B-деревьев, VACUUM,
REFRESH MATERIALIZED VIEW).
В этих случаях имеется процесс-лидер, инициирующий запуск рабочих
процессов и получающий от них информацию.
3. Логическая репликация (для процессов на стороне сервера-
подписчика).
Общее количество фоновых процессов в системе ограничено
значением параметра max_worker_processes, и отдельными
параметрами ограничено количество процессов для каждой из трех
категорий. Если в пуле недостаточно фоновых процессов, то обработка
будет выполняться последовательно, а не параллельно (а логическая
репликация и вовсе не будет работать).
6
Прикладные задачи
Некоторые идеи
планировщик заданий внутри СУБД
асинхронная обработка событий
распараллеливание сложной обработки данных
автономные транзакции
и другое
Но пользовательские задачи неудобно писать на языке C
Кроме штатного использования, фоновые процессы можно
приспособить и для решения пользовательских задач.
Например, можно организовать планировщик заданий внутри СУБД.
В отличие от, например, cron, такой планировщик не будет зависеть
от используемой операционной системы. (Планировщик внутри СУБД
реализован в Postgres Pro Enterprise и рассматривается в курсе
PGPRO).
Можно выполнять асинхронную обработку событий (что будет подробно
рассмотрено в одноименной теме).
Можно распараллеливать сложную длинную обработку больших
объемов данных.
Можно реализовать автономные транзакции, хотя и весьма дорогим
способом. (В Postgres Pro Enterprise имеются автономные транзакции,
они рассматриваются в курсе PGPRO).
И так далее.
Однако писать прикладные задачи на языке С крайне неудобно
и требует неоправданно высокой квалификации.
7
Расширение dblink
Назначение
выполнение произвольных SQL-команд на удаленном сервере
в качестве удаленного сервера может выступать и локальный
Плюсы
стандартное расширение
Минусы
фоновые процессы не используются,
устанавливается новое соединение
Одно из возможных решений — использовать расширение dblink,
которое предназначено для выполнения SQL-запросов на удаленном
сервере PostgreSQL (в качестве удаленного может выступать и
локальный сервер).
Это проверенное временем стандартное расширение. Однако оно
не использует механизм фоновых процессов — устанавливается
полноценное новое соединение с сервером, что существенно дороже.
9
Расширение pg_background
Назначение
возможность выполнить команду SQL в фоновом процессе
команда может вызвать подпрограмму на любом серверном языке
Плюсы
используются фоновые процессы
Минусы
стороннее расширение
Есть и другое решение, которое позволяет прикладным разработчикам
воспользоваться фоновыми процессами — стороннее расширение
pg_background:
Фактически это небольшая обертка над низкоуровневым API фоновых
процессов, позволяющая запускать в фоновом режиме произвольные
команды SQL. Разумеется, таким образом можно вызывать хранимые
функции и процедуры, написанные на любых серверных языках
программирования (например, PL/pgSQL).
11
Итоги
Сервер предоставляет механизм фоновых процессов
Фоновые процессы используются для внутренних целей,
но могут быть использованы и для прикладных задач
Расширение pg_background позволяет реализовывать
фоновые процессы на процедурных языках
12
Практика
1. Реализуйте расчет рейтинга книг на основе данных о голосах
пользователей «за» и «против».
Чтобы не допускать разрастание таблицы, выполняйте
обновление пакетами по N строк. Между частичными
обновлениями запускайте очистку.
Оформите обновление в виде хранимой процедуры,
принимающей N как параметр.
2. Выполните процедуру обновления в фоновом режиме.
1. Рейтинг книги оценивается числом от 0 до 1.
«Наивная» формула для определения рейтинга может быть такой:
votes_up / (votes_up + votes_down), если votes_up + votes_down > 0;
0, иначе.
Недостаток этой формулы показывает пример: книга, набравшая 100
голосов «за» и 1 голос «против», получит меньший рейтинг, чем книга,
набравшая всего один голос «за».
Можно подумать над более справедливой формулой, а можно
воспользоваться уже готовой функцией public.rating.
Пакетное обновление рассматривалось в практике к теме «Очистка».
Здесь применим тот же подход. Однако подумайте над тем, как
пересчитывать рейтинг только тех книг, для которых это необходимо.
Команда VACUUM не может быть вызвана внутри транзакции, но ее
можно выполнить как отдельную SQL-команду в фоновом процессе.
13
Практика+
1. Фоновый процесс не будет запущен, если запуск приведет
к превышению числа допустимых процессов.
Напишите функцию-обертку для pg_background_launch,
которая пытается запустить процесс N раз с интервалом
в одну секунду.
2. Сравните накладные расходы на порождение процесса
расширений dblink и pg_background, многократно выполняя
простой запрос.
1. Предварительно исследуйте, как функция pg_background_launch
сигнализирует об ошибке. Для этого удобно уменьшить значение
параметра max_worker_processes, но учтите, что один фоновый
процесс в системе уже запущен (logical replication launcher) —
не уменьшайте значение до 1.
Обработка ошибок рассматривается в курсе DEV1.
2. Разумеется, накладные расходы dblink будут существенно зависеть
от способа аутентификации (в нашем случае — проверка пароля scram-
sha-256).