#postgresql #plpgsql #postgresql-13
Вопрос:
Я пишу функцию для сбора строк из системного представления pg_stat_activity (PostgreSQL 13).
Внутри этой функции у меня есть простой цикл для вставки данных pg_stat_activity в таблицу журнала.
Проблема в том, что когда я запускаю функцию, она вставляет строки, действительные в первую секунду, и дублирует их позже. Похоже, функции работают как единая транзакция и получают данные из моментального снимка строк с момента первого запуска. Как я могу запустить функцию «тело» в нескольких отдельных транзакциях, чтобы получить результат за каждую секунду, или какой обходной путь я могу найти?
CREATE OR REPLACE FUNCTION public.fn_activity(
integer)
RETURNS void
LANGUAGE 'plpgsql'
--COST 100
--VOLATILE PARALLEL UNSAFE
AS $BODY$
declare counter integer := 0;
begin
while counter < $1 loop
raise notice 'Counter %', counter;
counter := counter 1;
insert into public.pg_stat_activity_log("time",datid,datname,pid,leader_pid,usesysid,usename,application_name,client_addr,client_hostname,
client_port,backend_start,xact_start,query_start,state_change,wait_event_type,wait_event,state,backend_xid,backend_xmin,query,backend_type)
SELECT now()::time(0),datid,datname,pid,leader_pid,usesysid,usename,application_name,client_addr,client_hostname,client_port,backend_start,xact_start,query_start,
state_change,wait_event_type,wait_event,state,backend_xid,backend_xmin,query,backend_type
from pg_stat_activity;
raise notice '-------';
PERFORM pg_sleep(1);
end loop;
return;
END;
$BODY$;
truncate table public.pg_stat_activity_log;
select public.fn_activity(60);
В настоящее время у меня есть результат только для 14:53:15, но мне нужно иметь:
14:53:15
14:53:16
14:53:17
14:53:18
Спасибо!
Комментарии:
1.
now()::time(0)
может быть упрощено доlocaltime
илиlocaltime(0)
Ответ №1:
Значения в pg_stat_activity
не изменяются, пока вы находитесь в транзакции, потому что данные считываются только один раз, а затем кэшируются в частной памяти сеанса базы данных.
Поскольку функция всегда выполняется в одной транзакции, она всегда будет видеть одни и те же значения pg_stat_activity
, независимо от того, соответствует ли это действительности или нет.
Смотрите комментарий к функции из pgstat_read_current_status
in src/backend/utils/activity/backend_status.c
, который копирует данные:
/* ----------
* pgstat_read_current_status() -
*
* Copy the current contents of the PgBackendStatus array to local memory,
* if not already done in this transaction.
* ----------
*/
Комментарии:
1. Ищу обходной путь…
2. @OlegAlekseiev: вы могли бы использовать процедуру, а затем выполнять фиксацию после каждой вставки