Una query di lunga durata di Postgres viene interrotta se la connessione viene persa / interrotta?


20

Se apro una connessione a Postgres e lancio una query di lunga durata, quindi interrompo la connessione (ad es. Interrompi il processo client che ha aperto la connessione), la query di lunga durata continuerà a essere eseguita o verrà automaticamente interrotta? È configurabile?

(Sto usando Postgresql 9.2.9)

Risposte:


32

"Dipende".

Se il client svanisce a causa della perdita della connessione di rete, la query generalmente verrà eseguita fino a quando non verrà recuperata abbastanza righe per riempire il buffer di invio della rete, quindi arrestarsi e bloccarsi fino a quando la connessione TCP si interromperà, a quel punto verrà interrotta. Se viene completato prima di riempire il buffer di invio TCP, verrà completato correttamente, quindi se è autocommit la query eseguirà il commit.

Se il client viene ucciso in modo tale che il sistema operativo del client possa riferire al server tramite un TCP RST (come un client segfault / crash, SIGTERM, SIGKILL, ecc.), Il server PostgreSQL imposterà il flag di interrupt. La prossima volta che la query verifica la presenza di interruzioni durante l'esecuzione, vedrà il flag e si interromperà. A volte una query potrebbe svolgere un lavoro pesante per la CPU all'interno di un codice che non verifica la presenza di interruzioni - alcune estensioni e alcuni punti all'interno del core PostgreSQL - nel qual caso potrebbe non notare l'interruzione per lungo tempo e continuare a funzionare. Praticamente vedrà sempre l'interruzione e l'interruzione prima di completare e confermare se si tratta di autocommit.

Se il client viene ucciso da qualcosa di simile a un riavvio improvviso del sistema operativo, in modo che l' host client improvvisamente non sappia nulla della connessione TCP ma possa ancora rispondere sulla rete, la query verrà probabilmente interrotta la prima volta che interviene per scrivere una riga, come Jeff ha detto, perché l'host del client invierà un TCP RST in risposta al primo pacchetto inviato dal server dopo il riavvio. PostgreSQL controlla gli interrupt ad ogni riga che invia.

Questo comportamento non è configurabile. Per quanto riguarda PostgreSQL se il client se ne va, il suo compito è quello di terminare qualsiasi domanda in esecuzione sul client. Per cambiare che avresti bisogno di un tipo di token di completamento della query che potresti ottenere all'avvio della query, quindi utilizza per chiedere al server la query tramite un'altra connessione in un secondo momento. In sostanza dovresti implementare query asincrone / in background. Forse una bella funzionalità, ma attualmente non supportata.

Se la query è autocommit o se la query era COMMITa bordo durante il periodo in cui il client è stato ucciso / perso la connessione, è possibile che una transazione si trovi in ​​uno stato indeterminato in cui il client non sa se o non è commesso. Non c'è modo reale di scoprirlo, se non quello di cercare gli effetti della transazione sui dati.

Laddove ciò sia inaccettabile, è possibile utilizzare il commit in due fasi e un gestore delle transazioni sul lato client.


1
Caspita, proprio quello che cercavo, un'ottima risposta dettagliata! Grazie @Craig_Ringer!
Rob Bednark,


2

Continuerà a funzionare fino a quando non tenta di restituire le righe alla connessione e rileva la rottura. Pertanto, per una query che esegue tutto il lavoro prima di restituire qualsiasi riga, verrà sostanzialmente eseguita fino al completamento.


Grazie @jjanes. Puoi indicare la documentazione o il codice sorgente che indica questo?
Rob Bednark,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.