Blog

Postgres SQL-Statement Timeout
Bildschirmfoto 2016-08-24 um 15.49.54_0.png
 
Wenn man einen Datenbankserver betreibt muss man sich Gedanken machen was passiert, wenn der Server zu lange für Anfragen braucht.
Zum einen kann es sein, dass das bewusst lang laufende Queries sind, z.B. für Datenanalysen oder Umfangreiche Updates von Daten. Zum anderen handelt es sich aber um Fehler in den SQL-Statements. Diese würden dann andere schnellere Anfragen blockieren und ggf. sogar die ganze Web-Anwendung lahm legen. Wie kann man in Postgres das timeout einstellen und was sollte man da einstellen.

Die offizielle Doku dazu ist hier: https://www.postgresql.org/docs/9.3/static/runtime-config-client.html

Der globale timeout wird in der Konfigurationsdatei data-path/postgresql.conf in der Variable
statement_timeout
eingestellt.

Alle Statements, die länger als die angegebene Zeit in ms dauern werden abgebrochen mit einer Fehlermeldung. Gemessen vom Zeitpunkt an wenn die Anfrage den Server erreicht.
Ein Wert von 0 Schaltet den timeout aus. Und ja, wenn man die Kommentierung rausnimmt und dann da 0 steht, ist der timeout aus.
Ein reload der Konfigurationsdatei sollte reichen, aber stoppen und starten geht auch. Dann aber auch den Web-Container neu starten.
Aber nun zur letzten und entscheidenden Frage. Welche Bedenken gibt zum Ausschalten des timeouts.
Ich denke das liegt klar auf der Hand. Wenn man den timeout in der postgresql.conf ausschaltet, gilt das für alle Prozesse, also auch für solche die abgebrochen werden sollen, weil sie auf Grund von Fehlern der Anfrage zu lange dauern und dadurch andere blockieren würden.
Postgres sagt dazu:
"Setting statement_timeout in postgresql.conf is not recommended because it would affect all sessions."
Wie ich schon sagte.
Aber was kann man tun?
Zum einen könnte man einen sinnvollen Wert nehmen, der noch vertretbar ist, sagen wir 3 Minuten. Aber welche Query läuft 3 Minuten?
Es gibt viele, die sollten viel schneller laufen. Alle, die in kvwmap verwendet werden und wo der Nutzer drauf wartet.
Es gibt vielleicht aber auch solche die länger laufen sollen, z.B. Analysen oder Ex- und Importe in Scripten.

Man kann das timeout auch vom Client aus setzen.
Dazu wird einfach im Script vor der lange dauernden Anfrage
SET statement_timeout=180000;
gesendet und die danach ausgeführten haben ein timeout von 3 Minuten.

Für Importe, Exporte, Analysefunktionen, Verschneidungen etc. die man nur scriptbasiert macht, vom Cron-Job oder händisch gesteuert, würde sich diese Vorgehensweise anbieten.
Für alle anderen Anfragen sollte man vorher analysieren wie lang diese normalerweise laufen und diesen Wert mit Puffer nach oben einstellen.
Sollte dann noch mal ein timeout auftreten, ist das wegen eines echten Fehlers, weil z.B. eine Query falsch definiert wurde. Dann sollte das timeout aber auch Sinn machen und man kann die Query beheben und danach passt sie wieder zum timeout.
Wichtiger ist in diesem Zusammenhang vielleicht eher das logging. Damit man überhaupt mal mitbekommen wie lange Queries dauern, sollte man das mal loggen und anschließend analysieren.
Dazu muss
logging_collector = on
log_directory = 'pg_log'
log_min_duration_statement = 30

gesetzt sein. Die letzten beiden kann man natürlich modifizieren.
Es gibt weitere Einstellungen mit denen man auch gleich den Query-Plan dazu mitloggen kann debug_print_plan = on etc.
Wenn man allerdings lang laufende Queries gefunden hat, müssen diese eh noch mal geprüft werden und man kann den Query-Plan auch selber aufrufen mit

EXPLAIN sql;

oder in pgadmin "Abfrage Zerlegen".

Die SQL-Statements, die vom Web-GIS kvwmap kommen und an die Datenbank gehen hinsichtlich ihrer Laufzeit zu prüfen ist zwar im Prinzip unsere Aufgabe schon bei der Entwicklung von Funktionen, jedoch hängen die Anfragen natürlich im erheblichen Maße von den Layerdefinitionen ab, die Ihr verantwortet.
Wenn Ihr also langsame Queries findet, bei denen Ihr Euch nicht erklären könnt warum die lange dauern, bzw. die nicht besser werden durch entsprechende Indizierung etc., dann lasst uns das wissen. Vielleicht kann man ja auch was am Quellcode optimieren.
Fazit: Generell timeout ausschalten wird nicht empfohlen. Statt dessen sollte man die Durchschnittlichen Laufzeiten kennen, ein dazu passendes timeout wählen und für bekannte lang laufende Queries vom Client aus vorab ein längeres timeout setzen. Gruß Peter

  Datensatz auswählen
Blog alle auswählen
  • als Diagramm ausgeben