Отключение клиента во время долгого запроса


#1

А расскажите, пожалуйста, как реагирует postgres на отключение клиента во время выполнения запроса? Когда клиент отправляет COMMIT: сразу со всем запросом или нет? Можно как-нибудь сделать так, чтобы клиент отправил на выполнение долгий запрос и мог отключится, а бэкенд закоммитил всё после завершения?


#2

А расскажите, пожалуйста, как реагирует postgres на отключение клиента во время выполнения запроса?

Видит что клиент отвалился (если видит) и прерывает запрос.

Когда клиент отправляет COMMIT: сразу со всем запросом или нет?

Так как клиент написан смотря. Просто 1 SQL команда она и без Begin/commit выполняется транзакционно.

Можно как-нибудь сделать так, чтобы клиент отправил на выполнение долгий запрос и мог отключится, а бэкенд закоммитил всё после завершения?

Нет (штатными методами).


#3

Иногда бекэнд может выполнять запрос до упора и понять что клиент отвалился уже после того как запрос выполнился. Keepalive как такогого между бекендом и клиентом нет. Сталкивались неоднократно что на серваке остаются жить бекенды без соединений со стороны клиента. Ладно бы они ресурсов не потребляли, потребляют и под 100%.
Проверить такое можно просто - запустить вставку, например боль менее толстых записей(100-1000 строк int,md5(txt) )в pg с использованием 1000 соединений и того же pgbench и после того как система встанет колом отрубить pgbench. Долгое время бекенды будут жить без клиентских подключений и потреблять при этом ресурсы системы


#4

Бэкенд узнает о том, что у него отвалился сокет только при попытке в него записать, а писать в него он будет только после завершения выполнения запроса, чтобы отправить клиенту результаты.
Помочь может параметр statement_timeout, но значения для него лучше выбирать консервативные, иначе есть риск отстрелить просто долго выполняющийся запрос.


#5
postgres=# create extension dblink;
CREATE EXTENSION
postgres=# create table test(id int);
CREATE TABLE
postgres=# SELECT dblink_connect('pg', 'dbname=postgres');
 dblink_connect
----------------
 OK
(1 row)

postgres=# select  dblink_send_query('pg','insert into test select id from generate_series(1,10000000)as id ');          dblink_send_query
-------------------
                 1
(1 row)

postgres=# \q
[postgres@thunder2 tmp]$ /home/postgres/usr/local/pgproee96/bin/psql
psql (9.6.9)
Type "help" for help.

postgres=# select count(*) from test;                                                                                    count
-------
     0
(1 row)

postgres=# select count(*) from test;
  count
----------
 10000000
(1 row)


#6

Григорий, а write в закрытый сокет происходит до фиксации транзакции или как?


#7

После фиксации транзакции.


#8

У нас сейчас пилится патчик, чтобы бэкенд pollом или selectом изредка сокет под собой шупал.