In meiner Anwendung verwaltet Spring den Verbindungspool für den Datenbankzugriff. Hibernate verwendet diese Verbindungen für seine Abfragen. Auf den ersten Blick habe ich keine Probleme mit dem Pool: Er funktioniert korrekt mit gleichzeitigen Clients und einem Pool mit nur einer Verbindung. Ich kann viele Anfragen ausführen, also denke ich, dass ich (oder Spring) keine offenen Verbindungen belasse.
Mein Problem tritt nach einiger Zeit der Inaktivität auf (manchmal 30 Minuten, manchmal mehr als 2 Stunden). Dann, wenn Hibernate etwas sucht, dauert es zu lange. Wenn ich log4j level auf TRACE setze, bekomme ich diese Logs:
%Vor%Hier wird es für ca. 2 - 10 Minuten eingefroren. Aber dann fährt fort:
%Vor%Danach funktioniert es ohne weitere Probleme bis zu einem anderen Zeitraum der Inaktivität. IMHO scheint es, als ob der Verbindungspool eine ungültige / geschlossene Verbindung zurückgibt, und wenn Hibernate das erkennt, eine andere Verbindung zum Pool anfordern.
Ich weiß nicht, wie ich dieses Problem lösen kann oder was ich tun kann, um es zu begrenzen. Jede Hilfe, die dies erreicht, wird zu schätzen wissen.
Danke.
EDIT: Nun, es war schließlich eine Firewall-Regel. Die Datenbank erkennt, dass die Verbindung unterbrochen wurde, aber pool (dbcp oder c3p0) nicht. So versucht es die Datenbank ohne Erfolg abzufragen. Was für mich immer noch seltsam ist, ist, dass die Timeout-Zeit sehr variabel ist. Vielleicht ist die Regel besonders seltsam oder die Firewall funktioniert nicht richtig. Wie auch immer, ich habe keinen Zugang zu dieser Maschine und kann nur auf eine Erklärung warten. : (
Ich hatte solche Probleme schon vorher, als sich die Datenbank in einer separaten Box befindet und dazwischen eine Firewall ist, die auf Timeout-Verbindungen im Leerlauf eingestellt ist.
Unter bestimmten Umständen schneidet die Firewall die Verbindung so ab, dass das JDBC-Ende sie nicht erkennt und der Versuch, sie zu verwenden, zu einer unbestimmten Blockierung führt.
In meinem Fall war es ein benutzerdefinierter Verbindungspool, der eine Testabfrage über die Verbindung gesendet hat, bevor sie aus dem Pool zurückgegeben wurde. Ich konfigurierte diese Testabfrage, um eine Zeitüberschreitung zu haben (mit Statement.setQueryTimeout), so dass es nicht unbegrenzt blockiert.
Überprüfen Sie die Konfiguration Ihrer Poolimplementierung. Normalerweise ist es Apache DBCP mit ein Timeout für jede Verbindung, nachdem sie geschlossen wurde.
In Ihrem Code sollten Sie keine Verbindungen aufrechterhalten. Holen Sie sich eines, benutzen Sie es, schließen Sie es sofort. Der Pool wird dafür sorgen, dass dies nicht zu viel kostet.
Eine Möglichkeit, das Zeitlimit für Leerlaufprobleme zu beheben, besteht darin, zwei Verbindungspools zu verwenden, von denen einer aktiv und der andere Standby ist (noch keine Verbindungen erstellt). Haben Sie einen Timer mit Trigger-Zeit viel weniger als FIREWALL_IDLE_TIMEOUT und wechseln Sie zwischen Verbindungspools. Ich habe das versucht und ITS funktioniert.
Wir haben das Problem mit ähnlichen Symptomen gelöst, die ebenfalls durch eine Firewall verursacht wurden.
Wir konnten das Problem umgehen, indem wir die testWhileIdle-Verbindungspool-Eigenschaft ändern, die verhindert, dass die Verbindung inaktiv wird, und die Firewall, die die Verbindung herunterfährt. Siehe Apache commons dbcp BasicDataSource . Hier ist eine Übung aus der Konfigurationsdatei persistentce-context.xml, die das Problem behob:
%Vor%Wahrscheinlich müssen wir nur testWhileIdle hinzufügen (standardmäßig false), aber die anderen beiden Eigenschaften für good measure hinzugefügt.
In unserem Fall sind hier einige der Protokolle, die wir gesehen haben. Beachten Sie, dass es in diesen Debug-Protokollen 16 Minuten dauern würde, die Verbindung zu öffnen, bevor die Verbindung verwendet werden konnte und dadurch alles hängen blieb. Es gab keine Fehler, die das Aufspüren erschweren.
%Vor%