Transaktion wird bei Fehlermeldung automatisch zurückgesetzt

Ah, jetzt wirds endlich Konstruktiv :wink:

Ich habe jetzt noch folgendes probiert in der psql-Konsole:

db=# \set autocommit off
db=begin;
db =# insert into totextindex (id) values (5);
INSERT 0 1
db =# insert into totextindex (id) values (5);
ERROR: duplicate key value violates unique constraint “totextindex_id_key”
db =# commit;
ROLLBACK

Leider nicht ganz das, was ich erwartet hatte…

natürlich ist er das … er muss mir auch nicht aus der doku vorlesen … denn in der doku hab ich schon gelesen …

und auch du scheinst geraden icht zu verstehen worum es geht …

die aussage war - ein fehler bei einer Operation in der TX macht sie automatisch ungueltig … das ist falsch … punkt.

und SAVEPOINTs sind nicht die loesung dieses problems hier

naja du solltest das mit der jdbc connection probieren - keine ahnung was der pg-client da macht … da stand ja, dass das client-abhaengig ist … ob das \set autocommit off da wat hilft … hmm … man sieht kein echo

aber ich muss sagen, dass das was ich da unten sehe doch i.o. ist … oder ueberseh ich gerade was ?

wieviel records wurden denn eingefuegt ?

Jaja … die Datensicherheit - also ob ORA oder MSSQL Server staendig mit Datenverlusten zu kaempfen haette und PG die Welt rettet - so ein quatsch

“Fehler” ist ein weiter begriff … es ist durchaus legitim ein INSERT abzusetzen wenn man 1. constraints pruefen will - um danach sowieso zu inserten - aber alternativ (wenn der constraint greift) was anderes machen moechte … dazu braucht man keine SAVEPOINTs …

es wurde kein Record eingefügt

das ist mist … ich probiers mal mit jdbc … 5 min bitte :slight_smile:

Wow, super, Danke!

Hier … funzt wie gewuenscht:

 ... connection erzeugen .. ist klar .. 
            con.setAutoCommit(false);
            Statement sx = con.createStatement();

            int n = 100;
            sx.execute("insert into test(id) values(" + n + ")");
            if (!sx.execute("insert into test(id) values(" + n + ")")) {
                sx.execute("insert into test(id) values(" + n + 2 + ")");
            }
            con.commit();
            con.setAutoCommit(true);

danach sieht die tabelle so aus :

id
[pk] integer
100
102

also was mir bisher auch nicht so bewusst war — bei jdbc gibt es kein explizites START TRANSACTION oder BEGIN … die TX ist automatisch gestartet wenn du ein DML kommando absetzt … und endet nach dessen ausfuehrung (bei auto-commit = on/true) oder eben erst bei commit() / rollback() …

ach was … die muehe mache ich mir nur um ak und ads zu ärgern … die müssen lernen, dass sie die weisheit auch nicht mit löffeln gefressen haben und v.a. auch mal annehmen dürfen,

  • dass hier nicht nur anfaenger fragen stellen
  • dass auch erfahrene entwickler anfaengerfehler machen dürfen
  • das verhalten von PG & Co nicht immer automatisch “richtig” ist

wie man hier eindrucksvoll sieht - gehen beide von falschen annahmen aus …

also bei mir kommt da ein Exception, sobald ich das insert mache:

org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "totextindex_id_key"
	at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:1592)
	at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1327)
	at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:192)
	at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:451)
	at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:336)
	at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:328)
	at agorum.tests.TestPostgres.doTestCommit(TestPostgres.java:164)
	at agorum.tests.TestPostgres.main(TestPostgres.java:394)

und damit bricht die ganze Schleife ab, wenn ich nun das Statement im IF in einen Try-Catch Block packe, dann erhalte ich beim nächsten insert (n+2), folgenden Exception:

org.postgresql.util.PSQLException: ERROR: current transaction is aborted, commands ignored until end of transaction block
	at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:1592)
	at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1327)
	at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:192)
	at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:451)
	at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:336)
	at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:328)
	at agorum.tests.TestPostgres.doTestCommit(TestPostgres.java:174)
	at agorum.tests.TestPostgres.main(TestPostgres.java:403)

Also mein Programm sieht nun so aus:

		try {
			Class.forName("org.postgresql.Driver").newInstance();
			//testcontent
			String cs =
				"jdbc :p ostgresql://localhost:5432/roi?user=xxx"+
				"&password=yy";

			Connection conn = DriverManager.getConnection(cs);
			conn.setAutoCommit(false);
			
      conn.setAutoCommit(false);
      Statement sx = conn.createStatement();

      int n = 100;
      sx.execute("insert into totextindex(id) values(" + n + ")");
      boolean a = false;
      
      try {
      	a = sx.execute("insert into totextindex(id) values(" + n + ")");
      }
      catch (Exception e) {
      	e.printStackTrace(System.err);
      }
      
      if (!a) {
        sx.execute("insert into totextindex(id) values(" + n + 2 + ")");
      }
      conn.commit();
      conn.setAutoCommit(true);			
		
			conn.close();
		}
		catch (Exception e) {
			e.printStackTrace(System.err);
		}

Das bedeutet, dadurch, dass ein Fehler auftrat, ist automatisch meine Transaktion für alle weiteren Dinge automatisch rollbacked worden…

Mach mal ruhig weiter so, du bestätigst damit nur akretschmer.

Aber wenn du, nur um uns zu ärgern endlich anfängst Dokumentation zu lesen hat das ganze vielleicht doch noch einen tieferen Sinn.

Ich weiß zwar nicht, was du mit “PG & Co” meinst, aber: PostgreSQL verhält sich so, wir haben dargelegt warum das so ist und wir haben sogar dargelegt wie man das sauber umgehen kann. Statt dessen tüftelt ihr beiden jetzt an Workarounds und müsst am Ende doch die aufgetretenen Fehler abfangen und korrigieren, bis dahin wäre ein SAVEPOINT auch zurückgerollt.

Wenn ihr zuviel Zeit habt - ich habe noch andere Sachen zu tun als mich mit symbiont zu streiten.

Ja ihr habt dargelegt, dass Postgres macht, was wir beobachten - toll … der Apfel fiel vom Baum weil er von Baum fiel.

Ihr behauptet - die TX sei ungueltig geworden! Wäre dem so, dürften SAVEPOINTS in der TX ja auch ungueltig werden - dem ist aber nicht so!

Ihr behauptet ORA und CO würden falsch arbeiten … das gegenteil behauptet sogar die Doku … ja die solltet ihr mal lesen.

Wahrscheinlich geht es wirklich nicht ohne Savepoints … das ist aber kein Problem anderer DB’s sondern ein Problem (wie ich finde) von PG … das Problem haben nämlich noch dutzende anderer Entwickler bei der Portierung von anderne DBMS …

Wo soll bitte die Konsistenz der DB in Gefahr sein, wenn man dem Entwickler die Ausnahmenbehandlung innerhalb der TX selbst ueberlaesst?

Was eine TX ist legt BEGIN und COMMIT fest … was sich dazwischen abspielt sollte dem Code ueberlassen sein …

hey - frag mich nicht was ich gemacht habe - inzwischen bekomme ich den Fehler auch - ich hab noch ein bisschen in boards geschnueffelt - andere haben das problem auch und “streiten” sich mit kollegen darum wie ein TX zu verlaufen hat

wahrscheinlich kommt man nich um KOSTSPIELIGE savepoints umher –

das wäre aber wieder eine sehr traurige erkenntnis um das fortschrittlichste DBMS der Welt :wink:

lach … das hier koennte man glatt durch dieses thema ersetzen

Es ist ein ABSOLUTER Quark, dass man ohne SAVEPOINT die komplette TX verliert (warum), während man mit SAVEPOINT munter weiter machen kann … da darfs dann ploetzlich Fehler geben und ich mich umentscheiden nen andern Weg zu gehen ? So ein Müll

Ja das mit den Savepoints hat auch Perfomance-Technische Gründe… ich denke, das meinten Sie mit kostspielig, ganz zu schweigen von dem “kostspieligen” Zeit-Aufwand, eine sehr große Applikation anzupassen an das verhalten von PG.

Klar, ich könnt einen JDBC-Wrapper schreiben, der das mit den Savepoints bei jedem insert/update durchführt, um so das verhalten anderer Datenbanken zu simulieren. Weiß jemand, was das tatsächlich an Performance bedeutet? Ich rede hier von 1000enden Updates/Inserts in einer Transaktion!

hier - das gleiche thema - da wird die sache beim namen genannt …
SAVEPOINT sind ein workarround

Nabble - PostgreSQL - jdbc - 25P02, current transaction is aborted, commands ignored until end of transaction block

schade …

naja “Sie” kannst Du :slight_smile: lassen …

ich sag mal so … es gibt sicher eine einfache methode an irgendeiner “zentralen” stelle des codes diesen unsinn einzubauen … der beste ort waere da wo das statement erzeugt wird … ich habe sowieso immer zwei anlaufstellen fuer solche geschichten - weil die connections fuers lesen und schreiben unterschiedlich erzeugt werden … d.h. soeine write-connection koennte halt schon geeignete statements generieren …

nur mal so als idee … ich weiss ja nicht wie deine anwendung aufgebaut ist

aber ebenso interessant zu lesen

Re: Weird behavior in transaction handling (Possible bug ?)

I can write code that works unchanged with Oracle, Sybase, DB2,
MySQL/InnoDB, Firebird and god knows what else. As soon as I throw
PostgreSQL into the mix, I need to handle a radically different
transaction semantics all of a sudden.

alles wunderbar

Ich versteh ehrlich gesagt noch immer nicht, wie es Dir dabei egal sein kann, wenn ein paar von denen fehlschlagen und du die anderen dennoch haben möchtest. Woher willst Du später wissen, welche Updates/Inserts geklappt haben und welche nicht? Wenn ich mir vorstelle, eine Buchhaltung würde so laufen…

Wie ads schon irgendwo sagte: ihr versucht etwas, was unsinnig ist. Ihr sucht nach einem Weg, das Verhalten von PG zu hintergehen. Dabei existieren Savepoints, um kritische Stellen in einer TX abzufangen. PG führt eine Transaktion gnadenlos nach dem Alles-oder-Nichts - Prinzip aus (abgesehen von Savepoints). Das kann es auch und sogar für DDL-Befehle. Das ist ein Kernfeature von PG.

Andreas

Ganz einfach deswegen, weil die Anwendung so programmiert wurde, dass sie dieses Verhalten ausnutzt. Reagieren auf Fehler, um dann zum Beispiel in der selben Transaktion sich daraufhin anders zu verhalten, also auf diesen Exception zu reagieren. Meisten führt das dann natürlich zu einem rollback der ganzen Transaktion, aber eben nicht immer (es kommt auf die Situation an).

Savepoints an zentraler Stelle eingebaut, könnten halt ein ziemliches Performance-Problem werden an dieser Stelle… aber das muss ich natürlich erst testen, ob dem auch so ist.

ich wuerde sagen, du verstehst vielmehr nicht was eine Transaktion alles sein kann … Das legt nicht Postgres fest - auch nicht du - auch nicht ads - sondern der Anwendungsfall!

Wenn innerhalb einer TX ein Insert aufgrund eines Constraint-Checks nicht durchgefuehrt werden kann (du nennst das “Fehler”), dann kann oliver.schulze (also der Anwendungsfall) darueber entscheiden ob diese Situation dazu führt ob die TX ungueltig wird (er ruft ROLLBACK auf) oder ob er eine andere Maßnahme ergreif.

Und wenn oliver.schulze der Meinung ist, dass die TX fortzufuehren ist, dann wird er seine Gruende haben. Wenn die Fortführung darin besteht weitere 35 Mrd INSERTS durchzuprobieren, dann ist das auch SEINE Sache.

Und wenn Du oder ads DAS nicht akzeptieren, geschweige denn verstehen wollt/könnt - dann ist der UNSINN bei EUCH zu suchen … und nicht bei ihm!

Ein TX hat NUR zu enden, bei:

  • COMMIT
  • ROLLBACK
  • connection closed/lost

alles andere ist totaler Unfug

… was er und ich zu akzeptieren haben - ist, dass PG nunmal so funktioniert … das bedeutet mit SAVEPOINTs arbeiten zu muessen - mehr aber auch nicht.
Nach Eurer tollen Argumentation dürfte es SAVEPOINTS garnicht geben. Denn was ist an einem “Fehler” bei einem INSERT plötzlich nicht “so fehlerhaft” nur weil man davor einen SAVEPOINT erzeugt hat?

Ach ja … die deutsche Fehlermeldung zum Problem:

FEHLER: aktuelle Transaktion wurde > abgebrochen> , Befehle werden > bis zum Ende der Transaktion ignoriert

??? … Ohne Worte