powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Повисшая транзакция
14 сообщений из 14, страница 1 из 1
Повисшая транзакция
    #34027680
thedix
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всех приветствую.

Работаю с pgsql 8.1.4.
Запускаю транзакцию, которая изменяет некоторые строки в таблице.
Код выглядит примерно так:
Код: plaintext
1.
2.
3.
4.
5.
$db->begin();
$res = $db->execute("INSERT INTO mytable (id, num, str, ts) VALUES (125, 1, 'str1', now())");
echo "waiting 10 seconds...\n";
sleep( 10 );
$db->execute("UPDATE mytable SET num = num+1 WHERE id=1");
$db->end();

Во время sleep-а скрипта обрываю подключение к бд, а потом убиваю скрипт.
Скрипт умирает, но процесс, обрабатывающий транзакцию остается работать на сервере в режиме "idle" 2 часа, при этом остаются заблокированными записи, которые начала править повисшая транзакция.
Это приводит к тому, что новая транзакция на тех же данных ждет время, указанное в statement_timeout. (по умолчанию - бесконечно)
Как сие разрулить?

Порылся в документации и нашел системную таблицу pg_locks, в которой хранится список текущих блокировок. К сожалению, там не указывается, с какого момента началась та или иная блокировка.
Для этого создается отдельная таблица примерно такой структуры:

Код: plaintext
1.
2.
3.
4.
5.
6.
CREATE TABLE trans
(
  pid int4 NOT NULL,
  xid int4 NOT NULL,
  ts timestamp NOT NULL
) 
где pid и xid - pid процесса и id транзакции, которая ожидает,
ts - с какого времени началась транзакция.

Далее каждую минуту в кроне читаем pg_locks, собираем инфу о начавшихся транзакциях и обновляем вышеописанную таблицу.
Как только ts достигла какого-то значения, посылаем процессу SIGTERM.

Думается, что существует какое-то стандартное решение, но я его не нашел.

Или можно ли как-то штатно изменить время ожидания процесса?
...
Рейтинг: 0 / 0
Повисшая транзакция
    #34027853
landy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Насколько я понял суть в следующем
Работаем по TCP/IP, после того как убили процесс в sleep
backend об этом никак не догадывается. Далее он работает и слушает сокет, через 90 минут(если не изменяет мне память) неактивный сокет закрывается
стеком, бакенд отваливается
...
Рейтинг: 0 / 0
Повисшая транзакция
    #34028197
thedix
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
landybackend об этом никак не догадывается
Да, вы все правильно поняли.
...
Рейтинг: 0 / 0
Повисшая транзакция
    #34028641
Andrew Sagulin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Может покрутить tcp_keepalives_* в postgresql.conf?
...
Рейтинг: 0 / 0
Повисшая транзакция
    #34029899
thedix
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Andrew SagulinМожет покрутить tcp_keepalives_* в postgresql.conf?
Да, действительно, попробую. Спасибо.

Порыл еще мануалы, нашел, что если включить stats_command_string, то в системной вьюхе pg_stat_activity появляется время начала запроса и его текущий статус.
Таким образом, свою таблицу создавать не надо, достаточно выполнить запрос вида:
Код: plaintext
1.
2.
3.
SELECT procpid AS pid, EXTRACT(EPOCH FROM (now()-query_start))::integer AS duration
FROM pg_stat_activity
WHERE current_query='<IDLE> in transaction';

Задача упрощается, но все равно как-то через одно место.
Есть еще варианты?
...
Рейтинг: 0 / 0
Повисшая транзакция
    #34031494
wbear
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
мож попробовать подписывать такие стремные коннекны на нотифаи..
те.

в приложении сразу после конекта делаеш например
Listen hup_notify;
потом все остальное..долгий селект...и т.д.

и переодически слать откудани-будь из крона например notify hup_notify;

есть подозрение что сразуже по приходу нотифая бакенд попытается его клиенту отправить по соединению .. и соответственно "узнает" что оно дохлое и благополучно помрет...
если получится отпиши плз.. т.к. самому интерестно.
...
Рейтинг: 0 / 0
Повисшая транзакция
    #34033464
thedix
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
wbearмож попробовать подписывать такие стремные коннекны на нотифаи

Пробовал - бэкенд все равно продолжает висеть.
...
Рейтинг: 0 / 0
Повисшая транзакция
    #34033681
st_serg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
из моего опыта, нотифаи приходят только после того как клиент чтото послал серверу и ожидает от него результата. Т.е. что бы получать notify от сервера необходимо было выполнять периодически какой либо запрос (например select 1)
...
Рейтинг: 0 / 0
Повисшая транзакция
    #34035193
wbear
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
не богатый опыт..
вот кусок на перле:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
my $fd = $db->func('getfd') or die "cant func getfd $!";
$db->do("LISTEN che");
my $rin ='';
my $rout;
vec($rin,$fd, 1 ) =  1 ;
my $timeout =  1 ;

while( 1 )
{
         ($nfound,$timeleft) = select($rout=$rin, undef, undef, $timeout ) or die "$!\n";
         while($ret = $db->func('pg_notifies'))
         {
              log_message("Event arrive ".$ret->[ 0 ]);
         }
}


асинхронные запросы обрабатываются аналогично.. так что как-то странно что
автор
Пробовал - бэкенд все равно продолжает висеть.

либо я чаво-то недо понимаю.
...
Рейтинг: 0 / 0
Повисшая транзакция
    #34035705
st_serg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
documentation
With the libpq library, the application issues LISTEN as an ordinary SQL command, and then must periodically call the function PQnotifies to find out whether any notification events have been received.

...
documentation
...
A better way to check for NOTIFY messages when you have no useful commands to execute is to call PQconsumeInput, then check PQnotifies.


т.е., насколько я понял, в любом случае активность должен проявлять клиент.
...
Рейтинг: 0 / 0
Повисшая транзакция
    #34035743
st_serg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
точнее в любом случае клиент должен проявлять активность (читать или проверять наличие данных на бекенде)

You should, however, remember to check PQnotifies after each PQgetResult or PQexec, to see if any notifications came in during the processing of the command.
...
Рейтинг: 0 / 0
Повисшая транзакция
    #34036470
thedix
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
wbearлибо я чаво-то недо понимаю.
Видимо, я тоже.
С нотифаями не работал, но сделал так, как вы писали.
То есть один клиент вызывает listen, потом после еще одного запроса связь отрубаю.
Одновременно другим клиентом делаю периодические notify.
А бэкенд как висел, так и висит, умирать не хочет.
...
Рейтинг: 0 / 0
Повисшая транзакция
    #34041887
wbear
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
st_serg
т.е., насколько я понял, в любом случае активность должен проявлять клиент.

нет.. посмотри внимательно.. перед $db->func('pg_notifies')
селект стоит с ожинадием возможности ЧТЕНИЯ с сокета..т.е ожиданием того что что-то придет на сокет.. т.е. сначало что-то отсылает бакенд клиенту, а только потом(если таймаут стоит в 0 есесно) мы вывалимся из селекта и заберем это функцией $db->func('pg_notifies') . т.е. в данном случае кокраз сервер инициатор..
вероятно ситуация меняется когда бакенд "занят" выполнением запроса.
...
Рейтинг: 0 / 0
Повисшая транзакция
    #34043188
thedix
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
wbear
т.е. в данном случае кокраз сервер инициатор..

Получается, что послав нотифай с одного клиента для другого, получатель должен сначала выполнить запрос и только потом уже проверить наличие нотифая.

Если получатель отвалился, то он не сможет послать бакэнду селект и потом спросить нотифай.
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Повисшая транзакция
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]