¿Se cancela una consulta de larga duración de Postgres si la conexión se pierde / se rompe?

20

Si abro una conexión a Postgres y emito una consulta de larga duración, y luego rompo la conexión (por ejemplo, finaliza el proceso del cliente que abrió la conexión), ¿continuará ejecutándose la consulta de larga duración o se cancelará automáticamente? ¿Es esto configurable?

(Estoy usando Postgresql 9.2.9)

Rob Bednark
fuente

Respuestas:

32

"Depende".

Si el cliente desaparece debido a la pérdida de la conexión de red, la consulta generalmente se ejecutará hasta que recupere suficientes filas para llenar su búfer de envío de red, luego se detendrá y se atascará hasta que la conexión TCP se caiga, momento en el cual abortará. Si se completa antes de llenar el búfer de envío TCP, se completará con éxito, por lo que si se confirma automáticamente, la consulta se confirmará.

Si el cliente se mata de una manera que el sistema operativo del cliente puede informar al servidor a través de un TCP RST (como un cliente segfault / crash, SIGTERM, SIGKILL, etc.), el servidor PostgreSQL establecerá el indicador de interrupción. La próxima vez que la consulta compruebe si hay interrupciones mientras se ejecuta, verá el indicador y abortará. A veces, una consulta puede estar haciendo un trabajo pesado en la CPU dentro del código que no busca interrupciones, algunas extensiones y algunos lugares dentro del núcleo de PostgreSQL, en cuyo caso es posible que no note la interrupción durante mucho tiempo y continúe ejecutándose. Sin embargo, casi siempre verá la interrupción y el aborto antes de completar y confirmar si se trata de confirmación automática.

Si el cliente es asesinado por algo así como un reinicio repentino del sistema operativo, de modo que el host del cliente de repente no sabe nada sobre la conexión TCP pero aún puede responder en la red, la consulta probablemente se cancelará la primera vez que intente escribir una fila, como Jeff dijo, porque el host del cliente enviará un TCP RST en respuesta al primer paquete enviado por el servidor después del reinicio. PostgreSQL busca interrupciones en cada fila que envía.

Este comportamiento no es configurable. En lo que respecta a PostgreSQL, si el cliente se va, su trabajo es terminar cualquier consulta que el cliente estaba ejecutando. Para cambiar eso, necesitaría algún tipo de token de finalización de consulta que podría obtener al inicio de la consulta, luego use para preguntarle al servidor sobre la consulta a través de otra conexión más adelante. Esencialmente, tendría que implementar consultas asíncronas / en segundo plano. Posiblemente una buena característica, pero actualmente no es compatible.

Si la consulta es de confirmación automática, o si su consulta estaba COMMITen curso en el momento en que mató al cliente / perdió la conexión, es posible que una transacción esté en un estado indeterminado donde el cliente no sabe si No se ha comprometido. No hay una forma real de averiguarlo, aparte de buscar los efectos de la transacción en los datos.

Cuando eso sea inaceptable, puede usar el compromiso de dos fases y un administrador de transacciones del lado del cliente.

Craig Ringer
fuente
1
¡Guau, justo lo que estaba buscando, una excelente respuesta detallada! Gracias @Craig_Ringer!
Rob Bednark
2

Continuará ejecutándose hasta que intente devolver filas a la conexión y detecte la rotura. Entonces, para una consulta que hace todo el trabajo antes de devolver cualquier fila, esencialmente se ejecutará hasta su finalización.

jjanes
fuente
Gracias @jjanes. ¿Puede señalar alguna documentación o código fuente que indique esto?
Rob Bednark