Rolf B: Nachtrag: PHP, MySQL Abbruch vermeiden

Beitrag lesen

Hallo Raketenwilli,

Autocommit

Autsch, ich habe offenbar viel zu selten mit MyISAM gearbeitet. Dass MyISAM auf Kosten von Tempo und Speicher auf vieles verzichtet, wusste ich, aber es weiß ja von ACID wirklich gar nichts und ist damit nichts weiter als dBASE mit SQL-Frontend.

Mit "automatisch transaktional" meinte ich das Verhalten von Transaktionsmonitoren (meine ersten Programme liefen auf IBM Großrechnern), die sich im Prinzip wie ein Webserver mit einem sehr dummen Browser verhalten: Drückt man auf dem Terminal ENTER oder eine Funktionstaste, wird ein Request an den TM geschickt (der dann dummerweise ebenfalls Transaktion heißt), von ihm verarbeitet und ein neuer Bildschirminhalt zurückgeschickt. TMs starten automatisch beim Beginn der Terminal-Transaktion eine DB Transaktion und committen die DB automatisch, wenn sie ohne Fehler durchläuft. Bei einem Abbruch (wegen Bug oder wegen Absicht) gibt's den DB Rollback.

Es hätte ja sein können, dass PHP sowas automatisch tut. Es hätte mich gewundert, aber beim lieben Rasmus weiß man ja nie.

Angesichts der (Nicht-)Fähigkeiten von MyISAM sehe ich jetzt aber, dass diese Möglichkeit einfach nicht besteht.

Nachdem wir das geklärt haben, möchte ich diesem Satz von Dir widersprechen:

Bei einem - offenbar gewünschtem - Nichtabbruch des Skriptes ist es auch notwendig, das ROLLBACK-Kommando an die Datenbank zu senden. Denn sonst wird die normalerweise eröffnete Transaktion (mit den bis dahin erfolgreichen, aber insgesamt unvollständigen Änderungen) am Ende der Verbindung, also des PHP-Skriptes automatisch „comittet“, also übernommen: „autocommit = ON“.

MyISAM kann keine Transaktionen. Da gibt's kein Autocommit und kein ROLLBACK. Wenn ich mit MyISAM 3 Statements durchführe und das dritte kackt ab, hilft nur ein RECOVER der DB. Oder ein manuelles Undo der bereits durchgeführten Änderungen.

InnoDB kann Transaktionen. Es hat per Default Autocommit, und das findet nach jedem einzelnen Statement statt. Läuft ein Statement auf einen Error, gibt's automatisch einen Rollback auf dieses Statement. Handbuch:

By default, MySQL runs with autocommit mode enabled. This means that, when not otherwise inside a transaction, each statement is atomic, as if it were surrounded by START TRANSACTION and COMMIT. You cannot use ROLLBACK to undo the effect; however, if an error occurs during statement execution, the statement is rolled back.

D.h. bei MyISAM würde ein ROLLBACK auf einen Error laufen ("Hä? Was's das?!") und bei InnoDB würde er nichts tun. Es sei denn, man hätte vorher mit START TRANSACTION eine Transaktion als Klammer um alle Statements geöffnet:

To disable autocommit mode implicitly for a single series of statements, use the START TRANSACTION statement

Falls eins von mehreren Statements in einer Transaktion auf einen Error läuft:

If a single SQL statement within a transaction rolls back as a result of an error…

Das steht bei Locking, aber es impliziert, dass auch bei einer manuell gestarteten Transaktion jedes einzelne Statement entweder vollständig oder gar nicht ausgeführt wurd.

Dann schriebst Du:

„(begintransaktion) Deaktiviert den Autocommit-Modus. Wenn der Autocommit-Modus deaktiviert ist, werden Änderungen, die über die Instanz eines PDO-Objekts an der Datenbank vorgenommen werden, erst dann bestätigt, wenn die Transaktion durch den Aufruf von PDO::commit() beendet wird.“

Das ist falsch, denn das startet tatsächlich eine Transaktion in der Transaktion - nur eben ohne autocommit.

Entweder verstehe ich Dich miss, oder Du irrst. Auch das MySQL Handbuch schreibt, dass es bei abgeschaltetem Autocommit steht eine aktive Transaktion gibt. Man kann darin mit START TRANSACTION eine Subtransaktion starten, ja. Muss man aber nicht, und wenn man dann am Ende den COMMIT oder ROLLBACK vergisst und die Session schließt (15.7.2.2):

If autocommit mode is disabled within a session with SET autocommit = 0, the session always has a transaction open. A COMMIT or ROLLBACK statement ends the current transaction and a new one starts.
If a session that has autocommit disabled ends without explicitly committing the final transaction, MySQL rolls back that transaction.

D.h. InnoDB verhält sich per Default so, wie ich es von Datenbanken wie MS SQL Server oder IBM DB2 kenne, und der er von Dir vorgeschlagene ROLLBACK ist nur dann nötig, wenn A. Meier vorher explizit eine Transaktion gestartet, bereits andere Statements ausgeführt und dann trotz Errors einen COMMIT programmiert hätte.

Man kann diesen Error übrigens entweder mit try/catch fangen, oder man schaltet den

Rolf

--
sumpsi - posui - obstruxi