Transaktion wird bei Fehlermeldung automatisch zurückgesetzt

Hallo,

folgendes Verhalten:

Ich beginne eine Transaktion und mache dann ein erfolgreiches “Insert”, dann mache ich noch ein Insert (welches absichtlich einen Fehler verursacht), das führt dazu, dass automatisch meine Transaktion zurückgesetzt wird (rollback), es ist also auch der erste insert nicht mehr durchgeführt worden.

Jetzt meine Frage, kann ich dieses Verhalten abschalten, also, dass es kein “auto-rollback” bei einem Fehler gibt, sondern die Transaktion bestehen bleibt?!

Das Verhalten ist zum Beispiel bei MySql und bei Oracle nicht so, dort kann ich die Transaktion, trotz Fehler, immer noch weiter nutzen.

Vielen Dank schonmal für Antworten!

Normal und gewollt.

Jetzt meine Frage, kann ich dieses Verhalten abschalten, also, dass es kein “auto-rollback” bei einem Fehler gibt, sondern die Transaktion bestehen bleibt?!

Nein.

Das Verhalten ist zum Beispiel bei MySql und bei Oracle nicht so, dort kann ich die Transaktion, trotz Fehler, immer noch weiter nutzen.

Dann ist das dort ein Fehler.

Vielen Dank schonmal für Antworten!

Wenn Du keine Transaktion willst, dann verwende keine. Oder verwende Savepoints.

Andreas

Tatsache, zumindest bei MySQL geht das. Die Oracle auf dem anderen Rechner will ich jetzt nicht hochfahren.

Also, meine Meinung dazu: wenn es einen Fehler gab ist irgendetwas in der Transaktion schief gelaufen. Die Transaktion hat keine Berechtigung mehr weiter Daten anzunehmen.

Andere Datenbanken mögen das anders sehen. Wenn man sich vor Augen hält das PostgreSQL sehr viel Wert auf Datensicherheit legt dann ist die hier gewählte Vorgehensweise verständlich.

Dann ist MySQL kapott. Definitiv. Bei ORA bezweifle ich das aber heftigst.

Also, meine Meinung dazu: wenn es einen Fehler gab ist irgendetwas in der Transaktion schief gelaufen. Die Transaktion hat keine Berechtigung mehr weiter Daten anzunehmen.

ACK.

Andreas

Um das noch mal klarzustellen: Ein Transaktion hat das Ziel, eine oder mehrere Manipulationen am Datenbestand als eine atomare Aktion ablaufen zu lassen. Beispiel: Kontoüberweisung. Von Konto A auf Konto B. Der Betrag wird von A abgebucht, und dann auf Konto B zugebucht. Das ist eine Transaktion. Entweder beide Buchungen, oder keine. Erst bei A abbuchen, und dann feststellen, daß Konto B nicht existiert, und dennoch den Betrag bei A abzubuchen, kann nicht das Ziel sein. Alles oder nichts.

Und wenn Du 100 Datensätze einfügen willst und der 98. schlägt fehl,
dann verhindert eine Transaktion zuverlässig, daß die Daten nachher nur zu 99% korrekt sind. Die Transaktion als solche schlug fehl, es ist dann Aufgabe der Applikation, damit fertig zu werden. Wenn MySQL von sich aus bei sehr vielen Inserts ab und an mal ein COMMIT sich erträumt dann ist das schlicht ein Bug.

PS.: ich empfehle bei der Arbeit mit psql eine ~/.psqlrc mit u.a. dieser Zeile:

\set AUTOCOMMIT off

Dies kann u.U. einem schon mal den Hals retten…

Andreas

Hmm, ja, mein kurzer Test mit sqlplus und START script.ext sagt etwas anderes …

WAS?

also für mich stellt sich zunaechst bei seinen ausfuehrungen die frage, WANN der fehler beim “2. Insert” auftritt

wenn er meint, dass direkt beim insert ein fehler auftritt, dann darf die transaktion an dieser stelle natuerlich NICHT zurueckgesetzt werden …

wenn er meint, dass der fehler des 2. insert beim COMMIT auftritt, dann ist das klar -> rollback

aber im obigen fall muss ich doch die chance haben darauf zu reagieren - um evtl was anderes zu committen …

ich kann mir vorstellen, dass er einfach nicht das gleiche szenario wie bei ORA etc implementiert hat.

das ist viel zu engstirnig … das kommt

  1. auf den isolationslevel an
  2. auf den anwendungsfall


    es ist naemlich durchaus sinnvoll insert-fehler (constraint-checks) in kauf zu nehmen - um zu ermitteln, ob fall a funktioniert - wenn nicht dann eben fall b … wenn der dann auch schief geht kann man die transaktion immernoch zuruecksetzen

waere das was du meinst richtig, haette man sich die funktion rollback sparen koennen … was meinst wozu es die gibt

Diese Frage beantwortet die Doku ausreichend.

PostgreSQL: Documentation: Manuals: PostgreSQL 8.3: ROLLBACK

Andreas

haha … ich weiss wozu es rollback gibt - nur hast du mal wieder nicht die rhetorik verstanden :slight_smile:

Noch einmal für Dich: das ein Fehler in einer Transaktion diese ungültig werden läßt. Alles was vorher/nachher in dieser Transaktion passiert, ist daher ungültig. Dazu sind Transaktionen da. Um innerhalb einer Transaktion Fehler abfangen zu können, gibt es Savepoints.

Ab jetzt habe ich aber keine weitere Lust, Dir und anderen die Doku vorzulesen. EOD.

Andreas

Tja … allein die Tatsache, dass es “SAVEPOINT” gibt, macht deine Aussage - ein Fehler wuerde die TX ungueltig machen - FALSCH …

Warum das so ist - sogar so sein MUSS - darfst du gern durch logische Überlegung selbst erörtern …

Denk mal darüber nach

du Schlaumeier lach

So seh ich das auch… Meine Frage hat ja eine heftige Diskussion hervorgerufen :slight_smile: Es ist einfach so, dass ich hier programmtechnisch selbst entscheiden möchte, was passiert, wenn ein Fehler bei einer einzelnen SQL-Operation auftritt, ob ich dann zum Beispiel selbst ein komplettes Rollback mache oder doch weiter mache. Klar, dass wenn beim commit was schief läuft, muss natürlich die gesamte Transaktion rückgängig gemacht werden.

Aber mit Oracle ist es definitiv so:

  1. sqlplus starten
  2. Transaktion beginnen
  3. insert machen (funktionierend)
  4. noch einen insert machen (absichtlich fehlerhaft)
  5. commit

Ergebnis: die Daten des ersten Inserts sind gespeichert.

Das geht dann aber auch in PG. Man arbeitet einfach ohne Transaktion.

Andreas

Ja, dieses eine Beispiel tut auch ohne Transaktion…

Transaktion brauch ich aber trotzdem, weil ich dann im Programm entscheiden will, wann ich ein rollback mache und wann nicht !!! Und in der Regel sind da mehr Operationen als nur 1 beteiligt :wink:

Deine Arroganz ist immer wieder amüsant …

Nimm das hier:

AUTOCOMMIT When on (the default), each SQL command is automatically committed upon successful completion. To postpone commit in this mode, you must enter a BEGIN or START TRANSACTION SQL command. When off or unset, SQL commands are not committed until you explicitly issue COMMIT or END. The autocommit-off mode works by issuing an implicit BEGIN for you, just before any command that is not already in a transaction block and is not itself a BEGIN or other transaction-control command, nor a command that cannot be executed inside a transaction block (such as VACUUM).[INDENT]Note: In autocommit-off mode, you must explicitly abandon any failed transaction by entering ABORT or ROLLBACK. Also keep in mind that if you exit the session without committing, your work will be lost.
[/INDENT][INDENT]Note: The autocommit-on mode is PostgreSQL’s traditional behavior, but autocommit-off is closer to the SQL spec. If you prefer autocommit-off, you might wish to set it in the system-wide psqlrc file or your ~/.psqlrc file.
[/INDENT]das was ORA und co macht ist also selbst lt. des heiligen PG-Evangeliums standardischer als das standardigste aller standard-DBMS …

Wie man da lesen kann gibt es auch eine Möglichkeit bei PG das “gewohnte” (ich wuerde sagen - das RICHTIGE! g) Verhalten herzustellen.

du solltest aufhoeren immer gleich beleidigt zu sein, wenn irgendwer mal ein problem mit deinem lieblingsspielzeug hat

auch Postgres ist nur ein Mensch :slight_smile:

@O.S

probiert habe ich das ganze nicht - was die PG-Dokue bei dem Transaktionskram naemlich verschweigt, ist das AUTOCOMMIT auch ein AUTOROLLBACK :wink: zu beinhalten scheint …

also der connection ein SET AUTOCOMMIT OFF senden before du die TX so verwenden moechtest … es kann ja nicht schaden ein SET AUTOCOMMIT ON zu senden wenn die TX zuende ist - damit man danach wenigstens weiss was det gute PG so tut …

FEHLER: SET AUTOCOMMIT TO OFF wird nicht mehr unterstützt

********** Fehler **********

FEHLER: SET AUTOCOMMIT TO OFF wird nicht mehr unterstützt
SQL Status:0A000


Auweia - PG 8.3

die Option ist aber in der 8.3er Doku zu finden … hmm … dann kannst ja probieren das in diesem seltsamen config file zu aendern … dann gilt das aber wohl fuer die gesamte server instanz …

Mist… geht tatsächlich nicht, bekomme dieselbe Meldung…

In der Doku steht:

The server-side autocommit setting was removed and reimplemented in client applications and languages. Server-side autocommit was causing too many problems with languages and applications that wanted to control their own autocommit behavior, so autocommit was removed from the server and added to individual client APIs as appropriate.

Jetzt meine Frage, wie stell ich das über JDBC ein?

Ich forsche mit dir … wenn du was findest poste es hier - interessiert mich auch

schon erledigt:

java.sql.Connection c =…;
c.setAutoCommit(autoCommit)

als Kommantar (nicht jdoc) steht im PG-JdbcTreiber:

/*

  • If a connection is in auto-commit mode, than all its SQL
  • statements will be executed and committed as individual
  • transactions. Otherwise, its SQL statements are grouped
  • into transactions that are terminated by either commit()
  • or rollback(). By default, new connections are in auto-
  • commit mode. The commit occurs when the statement completes
  • or the next execute occurs, whichever comes first. In the
  • case of statements returning a ResultSet, the statement
  • completes when the last row of the ResultSet has been retrieved
  • or the ResultSet has been closed. In advanced cases, a single
  • statement may return multiple results as well as output parameter
  • values. Here the commit occurs when all results and output param
  • values have been retrieved.
  • @param autoCommit - true enables auto-commit; false disables it
  • @exception SQLException if a database access error occurs
    */

Das erklaert natuerlich uach das Ungültigwerden der TX bei den ganzen üblichen PG-clients …
weil die auch so arbeiten werden … immer wenn ein Fehler auftritt - bei irgendeinem Kommando in der TX machen die ein Rollback … dann ist die TX natuerlich hinueber …

aber das ist eben NICHT das klassische Verhalten wie man es von einer TX erwartet - sondern das Verhalten “üblicher” PG-clients …

gruss

akretschmer ist nicht beleidigt, er hat nur keine Lust, dir ständig aus der Dokumentation vorzulesen. Ok, auf Dauer ist so etwas schon ein Grund, genervt zu sein.

Noch mal für dich, zum Mitschreiben: PostgreSQL nimmt das Thema Datensicherheit sehr ernst. Daher wird jeder Fehler, der in einer Transaktion auftritt, auch als Problem für die Transaktion gewertet und diese darf damit nicht commited werden. Wenn eine Transaktion nicht committed werden kann - welchen Sinn macht es noch, weitere Befehle anzunehmen?

So, und jetzt denke du mal logisch nach, wieso SAVEPOINT und ROLLBACK TO SAVEPOINT funktionieren … selbst wenn es in einer Transaktion Fehler gab kann ich die Transaktion zu einem funktionierenden Punkt zurückrollen ohne den Rest der Änderungen zu verlieren. Würde PostgreSQL einfach so alles wegwerfen weil es einen Syntax-Fehler gab dann würden auch SAVEPOINTs nicht funktionieren. Wenn du das ausgeknobelt hast und deinen Ton anpasst können wir uns weiter unterhalten.


auch Postgres ist nur ein Mensch > :slight_smile: >

Schwachsinn. Wir reden hier über meine Daten und nicht über Gefühle.


probiert habe ich das ganze nicht

Natürlich nicht, von dir lesen wir hier immer erst viel heiße Luft bevor du selbst auch nur einen Blick in irgendwelche Dokumtation wirfst.



BEGIN;
INSERT INTO tabelle (id, data) VALUES (1, 'abc');
SELECT id, data FROM tabelle;
SAVEPOINT sp1;
SELECT kaputt;
ROLLBACK TO SAVEPOINT sp1;
SELECT id, data FROM tabelle;
ROLBACK; oder COMMIT;

Das Leben kann so einfach sein.