COMMIT nie aufgerufen, ROLLBACK nötig?



  • Ilubummsium schrieb:

    tntnet schrieb:

    Man stelle sich einmal vor, eine Applikation würde nach query 1 mit einer exception diesen Block beenden und kein Rollback ausführen. Zu einem späteren Zeitpunkt möchte es eine andere Transaktion ausführen, die gelingt und mit die einem commit abgeschlossen wird. Damit würde sie auch query 1 committen, was sicher nicht beabsichtigt ist.

    Und warum macht man ein ROLLBACK dann nicht vor dem Query?

    Sicherheitshalber würde man dadurch alte Sitzungen sicher abschließen.
    Denn wenn das Programm wegen einem HW Fehler abstürzt, dann funktioniert auch der Rollback nicht mehr.

    Also wenn man so programmiert, dann hat man was falsch gemacht. Sicherheitshalber sollten solche offenen Transaktionen nicht vor kommen. Wenn doch, dann sollte man das Problem lösen und nicht "sicherheitshalber" irgendetwas machen, da man nicht sicher ist, ob das Programm richtig tickt.

    Ganz abgesehen davon hält eine offene Transaktion möglicherweise Locks, welches andere Zugriffe behindern würde. Daher ist es ein fataler Fehler, wenn man es für nötig hält "sicherheitshalber" noch mal ein rollback durchzuführen.



  • Th69 schrieb:

    @tntnet: ich bezog mich auf die technische Realisierung (nicht auf das logische ACID-Prinzip). Überlege dir mal wieso ein Rollback so viel länger dauert als ein Commit?

    Für Transaktions- und Datensicherheit gibt es zwei verschiedene Journal-Einträge in der Protokolldatei (before-image und after-image): Rollback, so daß bei einem Rollback die ursprünglichen Daten wiederhergestellt werden.

    Wie das technisch realisiert ist, ist abhängig vom DBMS.

    Viele machen es so wie du sagst. Andere schreiben vor dem Commit nur die neuen, geänderten Daten ins Logfile. Beim Commit wird im Logfile dann erstmal die Transaktion als committed gekennzeichnet - und ab dem Zeitpunkt gilt sie dann auch als committed. Dann wird ein "rollforward" gemacht (=die Änderungen aus dem Logfile ins Datenfile übertragen), und als letztes der Platz im Logfile wieder freigegeben.

    Die Variante die du beschrieben hast hat die Vorteile dass das Commit schneller geht, und dass man - wenn man das Logfile aufhebt - Transaktionen auch "zurückspulen" kann. Z.b. um aus einem Stand (aktueller Stand oder auch ein Full Backup) und den Log-Backups davor einen älteren Stand zu rekonstruieren.

    Die von mir beschriebene Variante hat die Vorteile dass sie mit kleineren Logfiles auskommt und dass Rollbacks schneller gehen. (Der Throughput leidet unter den länger dauernden Commits nicht wirklich, da die Zugriffe die in dieser Variante die Commits ausbremsen in der anderen Variante das Vorbereiten der Transaktion ausbremsen => die Transaktion als gesamtes dauert inetwa gleich lange.)



  • mhat schrieb:

    Wenn eines der queries eine exception wirft, wird COMMIT nie aufgerufen, somit ist doch gar kein ROLLBACK nötig?

    Wenn du statt des ROLLBACK die Verbindung zur Datenbank trennst, dann sollte das auch "OK" sein, denn dann wird das DBMS verutlich selbst ein ROLLBACK machen. (Macht zumindest jedes mir bekannte System.)

    Wenn die Verbindung zur DB bestehen bleibt, dann ist das ROLLBACK sehr sehr wichtig. Ohne bleibt nämlich die Transaktion offen. Bei einer "multiuser" Datenbank ist das sehr schlecht, da dadurch u.U. Transaktionen von anderen Usern/Programmen/Computern blockiert werden.
    Und bei einer "single user" Datenbank kommt auch nix gutes dabei raus. Entweder schlägt der nächste Versuch eine Transaktion zu beginnen fehl. Oder das DBMS macht beim nächsten Versuch eine Transaktion zu beginnen eine verschachtelte Transaktion auf, und übernimmt in dieser die (vermutlich unnvollständigen) Änderungen der "alten", unnvollständigen Transaktion. Evtl. könnten auch andere unerwartete/unerwünschte Dinge passieren.

    => ROLLBACK ist *nicht* optional.



  • Ich bin etwas erstaunt, auf welchem Level sich euere Transaktionsicherheit abspielt. Ihr redet von einer Transaktion innerhalb einer DB. Habe ich das richtig verstanden??
    Ist es nicht sinnvoller eine Transaktion in einem klar definierten Environment auszuführen? Das hätte doch den Vorteil, dass ich so viele DBs ansprechen kann wie es die Applikation erfordert.
    Habe ich innerhalb der Transaktion einen bestimmten Punkt erreicht setzt man einen Commit ab. Bei einer Bildschirmtransaktion würde ich das aber nicht empfehelen. Ein Commit kann eigentlich erst nach erfolgreicher Beendigung der Transaktion erfolgen - und das sollte automatisch geschehen. Sollte die Transaktion zu irgend einem Zeitpunkt "abschmieren" - sei es applikatorisch oder systembedingt - sollte der Rollback der Datenbanken ebenfalls automatisch erfolgen.
    Anders sieht es bei Prozessen aus, die ohne Bildschirmdialog ablaufen. Nehmen wir einmal an, zum Quartalsende laufen Buchungen, die in die Milliarden (Anzahl Buchungen) gehen. Was mache ich, wenn nach 5 Milliarden Buchungen das Programm "abschmiert" und nochmal 5 Milliarden Buchungen anstehen, die nicht ausgeführt werden konnten??
    Richtig: Ein schlauer Programmierer setzt klar definierte Commits resp Checkpoints ab. Wenn dann das Problem behoben ist, kann das Programm etwa via "Restart" auf dem Punkt aufsetzen, wann der letzte Commit resp. Checkpoint vor dem Fehler abgesetzt wurde - egal wieviele oder welche Datenbanken der Prozess benötigt.

    Oder habe ich da was falsch verstanden? 😉



  • Klar wäre es praktisch ein "klar definiertes Environment" zu haben, in dem man Transaktionen die beliebige Subsysteme involvieren machen kann. Nur sowas hat man im Allgemeinen nicht.
    Verteilte Transaktionen sind eine reichlich komplizierte Sache. Daher verzichtet man auch darauf, sofern es ohne all zu grosse Verrekungen möglich ist.

    Das Wort Bildschirmtransaktion ist mir auch nicht geläufig (und nicht nur mir nicht).

    Und was das abrechnen von milliarden von Datensätzen angeht: das ist kein Problem, da man es ja wunderschön in beliebig viele Transaktionen aufteilen kann. Hat ja auch keiner behauptet dass man das alles in einer grossen Transaktion machen müsste - das hast du bloss angenommen.

    Transaktion schrieb:

    Oder habe ich da was falsch verstanden? 😉

    Das vermute ich stark, ja 😉



  • hustbaer schrieb:

    Klar wäre es praktisch ein "klar definiertes Environment" zu haben, in dem man Transaktionen die beliebige Subsysteme involvieren machen kann. Nur sowas hat man im Allgemeinen nicht.
    Verteilte Transaktionen sind eine reichlich komplizierte Sache. Daher verzichtet man auch darauf, sofern es ohne all zu grosse Verrekungen möglich ist.

    Interessant - solche Systeme gibts schon seit bald 50 Jahren und laufen auch heute noch....

    https://en.wikipedia.org/wiki/CICS
    https://en.wikipedia.org/wiki/IBM_Information_Management_System#Transaction_Manager

    hustbaer schrieb:

    Das Wort Bildschirmtransaktion ist mir auch nicht geläufig (und nicht nur mir nicht).

    Ich kenne euere Terminologie nicht: Normal sagt man auch ein "in sich geschlossener Ablauf" - oder "Unit of Work". Ganz einfaches Beispiel: Wenn ein Sachbearbeiter sagen wir die neue Wohnadresse eines Kunden in einem Dialog am Bildschirm ändert. Dieser Vorgang beinhaltet ja einen Update der DB - gleichzeitig sollte die alte Adresse aber noch hinterlegt bleiben usw. egal wie man das von Fall zu Fall löst. Wenn dieser Vorgang erfolgreich abgeschlossen ist, ist auch die Transaktion erfolgreich abgeschlossen und alle Daten können persistent werden.

    hustbaer schrieb:

    Und was das abrechnen von milliarden von Datensätzen angeht: das ist kein Problem, da man es ja wunderschön in beliebig viele Transaktionen aufteilen kann. Hat ja auch keiner behauptet dass man das alles in einer grossen Transaktion machen müsste - das hast du bloss angenommen.

    Hast Du schon mal in einem Rechenzentrum gearbeitet, in dem die Nachtverarbeitung bis morgens 9 Uhr dauern kann? Dann gibst Du ganz schnell solche Ideen auf, zumal es bessere Lösungen gibt:

    https://en.wikipedia.org/wiki/Transaction_checkpoint#Recovery_process

    Ausserdem ist der Ablauf eines Programms, das milliarden Datensätze verarbeitet keine Transaktion sondern ein Prozess.

    hustbaer schrieb:

    Transaktion schrieb:

    Oder habe ich da was falsch verstanden? 😉

    Das vermute ich stark, ja 😉

    Soso 🕶



  • OK, dein Verständnis des Worts Transaktion unterscheidet sich deutlich von meinem (und vermutlich dem der meisten Entwickler).

    Transaktion schrieb:

    hustbaer schrieb:

    Klar wäre es praktisch ein "klar definiertes Environment" zu haben, in dem man Transaktionen die beliebige Subsysteme involvieren machen kann. Nur sowas hat man im Allgemeinen nicht.
    Verteilte Transaktionen sind eine reichlich komplizierte Sache. Daher verzichtet man auch darauf, sofern es ohne all zu grosse Verrekungen möglich ist.

    Interessant - solche Systeme gibts schon seit bald 50 Jahren und laufen auch heute noch....

    https://en.wikipedia.org/wiki/CICS
    https://en.wikipedia.org/wiki/IBM_Information_Management_System#Transaction_Manager

    Interessant - ich habe auch nicht geschrieben "so etwas gibt es nicht" sondern "so etwas hat man im Allgemeinen nicht". Schätz mal selbst wie viele Programmierer mit den von dir genannten Systeme arbeiten, und wie viele ohne. Dann bewerte meine Aussage neu, und schreib mir ob du sie immer noch "interessant" findest.

    Transaktion schrieb:

    hustbaer schrieb:

    Und was das abrechnen von milliarden von Datensätzen angeht: das ist kein Problem, da man es ja wunderschön in beliebig viele Transaktionen aufteilen kann. Hat ja auch keiner behauptet dass man das alles in einer grossen Transaktion machen müsste - das hast du bloss angenommen.

    Hast Du schon mal in einem Rechenzentrum gearbeitet, in dem die Nachtverarbeitung bis morgens 9 Uhr dauern kann? Dann gibst Du ganz schnell solche Ideen auf, zumal es bessere Lösungen gibt:

    https://en.wikipedia.org/wiki/Transaction_checkpoint#Recovery_process

    Holla, da hast du aber was nicht verstanden. Dein Link beschreibt wie man die DB nach einem Problem wieder in einen konsistenten Zustand bekommt. Wie das funktioniert ist mir bekannt. Dabei bekommst du aber einen Zustand wo sämtliche Transaktionen entweder komplett abgeschlossen sind, oder gar nicht vorhanden. D.h. wenn eine riesen Transaktion unterbrochen wird, kannst du die nicht einfach "fortsetzen" nach der "recovery". Du musst ganz von vorne anfangen.
    Weswegen man so grosse Dinge ja auch in mehrere Transaktionen aufsplittet -- damit man eben nicht ganz von vorne anfängt.
    Wenn man sehr doof ist, oder es nicht anders geht, macht man es Datensatz für Datensatz. Wenn es geht, und man schlauer ist, bearbeitet man dabei in einer Transaktion ein paar tausend/zigtausend Datensätze auf einmal, und schreibt danach irgend ein Zwischenergebnis, so dass man im Falle einter Unterbrechung nach dem letzten Zwischenergebnis fortsetzen kann.

    Vermutlich wird es auch Systeme geben die diesen Prozess automatisieren. Indem sie z.B. den kompletten Zustand der VM die den Prozess ausführt sichern, inklusive Checkpoint der DB Transaktion, so dass der Prozess automatisiert vom letzten Checkpoint fortgesetzt werden kann. Hier aber wieder: überleg dir wie viele Programmierer mit sowas arbeiten, und wie viele ohne so etwas auskommen müssen.

    Und nein, ich hab noch nie in einem Rechenzentrum gearbeitet. Aber ich habe bereits mehr als 1x Prozesse implementiert die so an die 3-4 Stunden laufen. Und weil ich so ein schlaues Kerlchen bin, hab ich das so gemacht, dass man nach einem Crash/Stromausfall/... den Prozess jederzeit fortsetzen kann, ohne mehr als ein paar Minuten Zeit zu verlieren.

    Transaktion schrieb:

    Ausserdem ist der Ablauf eines Programms, das milliarden Datensätze verarbeitet keine Transaktion sondern ein Prozess.

    Interessant - wieso hast du das dann im Zusammenhang mit Transaktionen erwähnt?



  • Kleiner Hint: in .NET musst du quasi nie ROLLBACK (Edit: manuell) ausführen, wenn du innerhalb des Gültigkeitsbereichs der Transaction kein Commit() durchführst, wird automatisch zurückgerollt.

    MfG SideWinder



  • @SideWinder
    Wenn du eine nicht committete Transaktion "disposed", dann machst du damit nen Rollback.
    "Nie ROLLBACK ausführen" ist also falsch. Wenn dann "nie manuell ROLLBACK ausführen".



  • SideWinder schrieb:

    Kleiner Hint: in .NET musst du quasi nie ROLLBACK ausführen, wenn du innerhalb des Gültigkeitsbereichs der Transaction kein Commit() durchführst, wird automatisch zurückgerollt.

    MfG SideWinder

    Das ist jetzt kein so besonderes Feature von .NET. Das kann und sollte man genau so in C++ implementieren und verwenden. Da gibt es schließlich Stack-Objekte und Destruktoren.


Anmelden zum Antworten