pg_background
Запуск команд в фоновом режиме.
Схема размещения:
ext
.Модуль дает возможность:
- Занимать пользовательскими вызовами фоновые процессы-обработчики.
- Размещать в этих процессах
sql
-команды: предложения, вызовы функций, процедур, анонимных блоков кода. При размещении вызова отводить область памяти сессии заданного размера для результатов вызова, получатьpid
выделенного процесса. - В памяти
dsm
отводить дескрипторы запущенных процессов, обращаться к ним по ранее полученнымpid
. - Ожидать завершения вызова.
- По завершении вызова получать результаты различных типов: выбранные данные, результаты процедур и функций, коды ошибок и подробные сообщения.
- Отсоединять процессы-обработчики без завершения текущего вызова и без контроля его результата.
Количество фоновых процессов, доступных для выполнения кода в заданный момент времени, определяется
max_worker_processes
(счетчик общий вместе с другими типами фоновых обработчиков).Допускается рекурсивное выполнение из фоновых операций вложенных (дочерних) фоновых операций. Глубина вложенности ограничена количеством доступных фоновых процессов.
Описание функций представлено в таблице.
Функция | Возвращаемое значение | Описание | Аргументы |
---|---|---|---|
pg_background_launch (sql TEXT, queue_size INT4 DEFAULT 65536) | int4 | Запускает фоновый обработчик, обрабатывающий указанную sql команду и возвращает pid обработчика | sql - sql команда;queue_size - размер буфера для получения результата |
pg_background_result (pid INT4) | record | Возвращается множество записей, включающих в себя результат вызова в случае успеха или подробности ошибки в случае сбоя. Тип record - не подлинный тип данных записи (коллекции значений других типов). Это только лишь заполнитель, который при каждом использовании требует явного объявления структуры записей | pid – pid обработчика |
pg_background_detach (pid INT4) | void | Отсоединяет фоновый обработчик, результат работы обработчика будут удалены из памяти без ожидания их обработки | pid – pid обработчика |
Представление
pg\_stat\_bg\_activity
строится на основе представления pg_stat_activity
по процессам с типом pg_background
.Имя столбца | Тип | Описание |
---|---|---|
datid | oid | OID базы данных |
datname | name | Имя базы данных |
pid | integer | Идентификатор процесса |
leader_pid | integer | Идентификатор ведущего процесса |
usesysid | oid | OID пользователя |
usename | name | Имя пользователя |
application_name | text | Название приложения |
backend_start | timestamptz | Время запуска процесса |
xact_start | timestamptz | Время начала текущей транзакции или NULL при отсутствии активной транзакции |
query_start | timestamptz | Время начала выполнения запроса, активного в момент сохранения данных, или, если поле state не active , то время начала выполнения последнего запроса |
state_change | timestamptz | Время последнего изменения состояния (поле state ) |
wait_event_type | text | Тип события, который ждет обслуживающий процесс, если это ожидание имеет место, в противном случае — NULL |
wait_event | text | Имя ожидаемого события, если обслуживающий процесс находится в состоянии ожидания, в противном случае — NULL |
state | text | Общее текущее состояние этого серверного процесса |
backend_xid | xid | Идентификатор верхнего уровня транзакции этого серверного процесса или любой другой |
backend_xmin | xid | Текущая граница xmin для серверного процесса |
query | text | Текст последнего запроса этого серверного процесса. Если поле state имеет значение active , то в этом поле отображается запрос, который выполняется в настоящий момент. Если процесс находится в любом другом состоянии, то в этом поле отображается последний выполненный запрос |
По умолчанию использование модуля разрешено только суперпользователям; предоставить доступ можно с помощью инструкции
GRANT
.Не допускается запуск в фоновых обработчиках команд
CREATE INDEX
и REINDEX
: это может привести к зависанию фонового обработчика и процесса (или цепочки процессов), которые их породили.Пользователь, который запустил команду в фоновом процессе, может отменить ее выполнение при помощи стандартной функции
pg_cancel_backend (pid integer)
или удалить фоновый процесс, используя стандартный вызов pg_terminate_backend (pid integer)
. Здесь pid
- pid
фонового процесса, полученный ранее в результате pg_background_launch
. Оба действия разрешены:- самому пользователю;
- ролям, являющимся членами роли, для которой отменяется команда / удаляется процесс;
- если команда запущена не от суперпользователя, то суперпользователям и ролям, которым выдано право
pg_signal_backend
; - если команда запущена от суперпользователя, то остальным суперпользователям.
Для функции, возвращающей
record
, фактическая структура типа результата определяется во время разбора вызывающего запроса. Поскольку ее результат не имеет предопределенной структуры, попытка вызвать функцию без явной инициализации типа результата закончится ошибкой:First_db=> SELECT * FROM pg_background_result(pg_background_launch('SELECT true')); ERROR: a column definition list is required for functions returning "record" LINE 1: SELECT * FROM pg_background_result(pg_background_launch('SELECT ... ') )
При каждом использовании такой функции тип результата необходимо объявить отдельно. При этом важно заранее задать структуру записи так, чтобы она соответствовала фактическим записям результата или хотя бы допускала неявное преобразование типов полей. При несовместимости объявленной структуры записи с фактической структурой результата возникнет другая ошибка:
Раскрыть type=sqlFirst_db=> SELECT * FROM pg_background_result(pg_background_launch('SELECT true')) AS (col1 INTEGER); ERROR: remote query result rowtype does not match the specified FROM clause rowtype
Исправить ошибку можно так:
Раскрыть type=sqlFirst_db=> SELECT * FROM pg_background_result(pg_background_launch('SELECT true')) AS (col1 BOOLEAN); col1 ------ t (1 row)
Наилучший способ для
pg_background_result
- использовать text
для команд, которые не предполагают выборку записей и объявлять фактический тип результата тогда, когда предстоит выбирать результат:First_db=> SELECT * FROM pg_background_result(pg_background_launch('INSERT INTO log VALUES (1, ''Шаг 01'', ''Начало обработки'')')) as (result TEXT); result ------------ INSERT 0 1 (1 row)
First_db=> \d log Table "sch1.log" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+--------- i | integer | | | step | text | | | result | text | | |
First_db=> SELECT * FROM pg_background_result(pg_background_launch('SELECT i, step, result FROM log')) AS (i integer, step text, result text); i | step | result ---+--------+------------------ 1 | Шаг 01 | Начало обработки (1 row)
При использовании переменной типа
record
каждое присваивание значения может устанавливать ее структуру заново. Функция же получает физический тип результата единственный раз, во время синтаксического разбора вызывающей команды, и сохраняет его на все время выполнения.Переменные типа
record
можно использовать в коде для хранения результатов функций типа record
, но это не отменяет инициализации типа результата перед вызовом функции.