Problem mit <IDLE> in transaction

Hallo zusammen!

In unserer Firma haben wir seit kurzem eine Anbindung an Postgresql. Beim Monitoring mit PGAdmin III sehe ich eine Menge in Transaction Prozesse, nach etwas Recherche konnte ich das Problem eingrenzen und habe festgestellt, dass dieses Problem nur SELECT-Statements und keine schreibenden Zugriffe betrifft (Postgresql startet wohl für SELECTS auch eine Transaktion, die wir dann aber nicht mit einem commit() oder rollback() beenden).

Meine Frage nun: Hat das irgendwelche negativen Auswirkungen auf unsere Anwendung oder die Datenbank? Und gibt es eine Möglichkeit, dieses Verhalten abzuschalten, das bei lesenden Zugriffen Transaktionen gestartet werden?

Vielen Dank im Vorraus!

Jein. Natürlich wird für das Resultset eines Selects irgendwo Speicher verbraucht. Abschalten? Ein COMMIT anhängen?

Ach ja: COMMIT, nicht COMMIT().

Andreas

Commit anhängen wäre bei dem Umfang unserer Software vom Aufwand nicht vertretbar, da wir dann hunderte Codestellen anpassen müssten und anschließend testen. Gibt es denn da keine andere Möglichkeit? Unsere Software läuft beim Kunden seit Jahren mit Oracle, MS SQL und DB2, daher versteh ich den Sinn nicht ganz, einen SELECT-Befehl in einer Transaktion auszuführen. Wegen dem Resultset: Ich schließe ja das Statement, dadurch wird auch der Speicher für das Resultset freigegeben.

Doch, commit(). Da das Kommando aus JAVA heraus abgesetzt wird :wink:

Welche Einstellung hat Autocommit in der Software?

Hi,

Autocommit ist auf false.

Dann wird nach einem COMMIT eine neue Transaktion gestartet und die bleibt wiederum offen, bis sie committed oder zurückgerollt wird.

Die Verbindung befindet sich quasi immer in einer Transaktion.

Daher dürfte auch deine Anzeige kommen.

Mir ist die Logik nicht ganz klar. Warum wird bei Autocommit=FALSE eine neue Transaktion gestartet? Was würde das z.B. bedeuten, wenn ich beispielsweise drei DML-Operationen auf mehreren Tabellen in einer Transaktion durchführen möchte? Bisher sieht unser Code in etwa so aus:

conn = getConnectionFromPool();

Statement s = conn.createStatement();
s.execute(“INSERT INTO Tabelle1…”);
s.close();

s = conn.createStatement();
s.execute(“UPDATE Tabelle2…”);
s.close();

s = conn.createStatement();
s.execute(“INSERT Tabelle3…”);
s.close();

conn.commit();

Was müsste ich nun ändern, damit ich diese Offenen Transaktionen loswerde? Autocommit darf ja während dieser Transaktion auf KEINEN FALL auf false stehen, da die Operation auf den drei Tabellen atomar bleiben muss.

Du könntest AutoCommit auf true stellen, dann wird jede Operation in seiner eigenen Transaktion durchgeführt.

Wenn du mehrere Operationen in eine Transaktion zusammenfassen willst, kannst du explizit eine (länger laufende) Transaktion mit BEGIN oder START TRANSACTION starten.

Dann sind offene Verbindungen im Regelfall nicht in einer laufenden Transaktion.

Ich hab das ganze mal mit einem Java-Testprogramm probiert. Mit Autocommit = FALSE bekomme ich keine Offene Transaktion (da ich hier das commit selber im Code setze). Lediglich bei einem SELECT passiert das (weil ich am Ende weder commit() noch rollback() aufrufe). Ich müsste also wahrscheinlich dem Connection-Pool nur sagen, dass er am Ende nochmal ein Commit ausführen soll, oder?

Eher der Anwendung, nicht dem Pool. Es ist nicht Aufgabe des Pools, ungefragt Änderungen zu committen.

Wenn die Anwendung das nicht tut, woher weißt du, ob die Änderungen wirklich “durch” sind oder ob es zu einem Abbruch aufgrund eines Fehlers kam?

Oracle macht das ganz genauso.
Ich meine auch DB2 macht das intern so.

Jede Datenbank ein vernünftiges Transaktions-Konzept implementiert muss auch ein SELECT in einer Transaktion laufen lassen. Ansonsten könnte statement-level consistency gar nicht gewährleistet werden.

Bei Oracle fällt das nur nicht so auf, weil es dort diesen Zustand “idle in transaction” so nicht gibt (bzw. so nicht angezeigt wird).

Richtig.

Ein SELECT bedeutet ja nicht, dass die Transaktion nur lesende Operationen durchführt. Intern kann eine Funktion aufgerufen werden, die irgendetwas ändert. Spätestens dann will man eine Transaktion haben.