Transaktionen und auto-commit
Jetzt, wo Sie via PDO verbunden sind, müssen Sie sich bewusst machen, wie PDO
Transaktionen verwaltet, bevor Sie anfangen, Abfragen auszuführen. Falls Sie noch
nie mit Transaktionen zu tun hatten, diese bieten 4 wichtige Features: Atomizität,
Konsistenz (Consistency), Isolation und Dauerhaftigkeit (Durability) (ACID).
Einfach gesagt wird alles in einer Transaktion, auch wenn es in Einzelschritten
ausgeführt wird, garantiert in sicherer Weise in die Datenbank eingetragen, ohne
Beeinträchtigung durch andere Verbindungen, wenn es abgeschickt wird. Aktivitäten in
Transaktionen können auch automatisch annulliert werden (wenn Sie es noch nicht
abgeschickt haben), was Fehlerbehandlung in Ihren Scripts einfacher macht.
Transaktionen werden typischerweise implementiert, indem Ihre Menge an Änderungen
"aufgespart" wird und dann in einem Rutsch abgearbeitet werden. Das hat den netten
Nebeneffekt, dass die Effizienz der Aktualisierungen drastisch erhöht wird. In
anderen Worten können Transaktionen Ihre Scripts schneller und möglicherweise auch
robuster machen. Aber Sie müssen sie korrekt verwenden, um davon zu profitieren.
Unglücklicherweise unterstützt nicht jede Datenbank Transaktionen, deswegen muss PDO
in einem "auto-commit" genannten Modus laufen, wenn Sie die Verbindung zum ersten
Mal öffnen. "Auto-commit" bedeutet, dass jede Abfrage, die Sie ausführen ihre eigene
implizite Transaktion besitzt, wenn die Datenbank das unterstützt, oder keine
Transaktion, wenn die Datenbank keine Transaktionen unterstützt. Wenn Sie eine
Transaktion benötigen, müssen Sie eine mit der Methode
PDO::beginTransaction() initiieren. Wenn der zu Grunde liegende
Treiber keine Transaktionen unterstützt, wird eine PDOException
geworfen (unbeachtet Ihrer Einstellungen zur Fehlerbehandlung: dies ist immer eine
ernste Fehlerbedingung). Wenn Sie dann in einer Transaktion sind, können Sie
PDO::commit() oder PDO::rollBack() benutzen,
um die Transaktion abzuschließen, abhängig vom Erfolg des Codes, den Sie während der
Transaktion ausgeführt haben.
Warnung
PDO überprüft nur auf Treiberebene auf Transaktionsfähigkeit. Wenn bestimmte
Laufzeitbedingunen ergeben, dass Transaktionen nicht verfügbar sind, wird
PDO::beginTransaction() trotzdem ohne Fehler true
zurückgeben, wenn der Server die Anfrage zum Start einer Transaktion akzeptiert.
Ein Beispiel wäre es, Transaktionen auf MyISAM-Tabellen in einer MySQL-Datenbank
zu verwenden
Wenn das Script endet oder die Verbindung im Begriff ist, geschlossen zu werden und
Sie eine Transaktion ausstehen haben, wird PDO automatisch einen Rollback
durchführen. Dies ist eine Sicherheitsmaßnahme, um Inkonsistenzen in dem Fall, dass
das Script unerwartet beendet wird, zu vermeiden - wenn Sie die Transaktion nicht
explizit ausgeführt haben, wird angenommen, dass etwas schiefgegangen ist, deswegen
wird zur Sicherheit Ihrer Daten ein Rollback durchgeführt.
Warnung
Der automatische Rollback wird nur durchgeführt, wenn Sie die Transaktion per
PDO::beginTransaction() starten. Wenn Sie manuell eine Abfrage
ausführen, die eine Transaktion startet, kann PDO nichts davon wissen und kann
deswegen auch keinen Rollback durchführen, wenn etwas schiefgeht.
Beispiel #1 Mehrere Abfragen in einer Transaktion
Im folgenden Beispiel nehmen wir an, dass wir einen Satz von Einträgen für einen
neuen Angestellten eintragen wollen, dem die ID-Nummer 23 zugeordnet wurde.
Zusätzlich zur Angabe der Basisdaten für diese Person müssen wir auch ihr Gehalt
festhalten. Es ist ziemlich einfach, zwei getrennte Aktualisierungen
durchzuführen, aber indem wir sie in PDO::beginTransaction()
und PDO::commit() einschließen, garantieren wir, dass niemand
anderes diese Änderungen sieht, bis sie komplett sind. Wenn etwas schiefgeht, wird
der catch
-Block alle seit Beginn der Transaktion durchgeführten
Änderungen rückgängig machen und dann eine Fehlermeldung ausgeben.
<?php
try {
$dbh = new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2',
array(PDO::ATTR_PERSISTENT => true));
echo "Connected\n";
} catch (Exception $e) {
die("Unable to connect: " . $e->getMessage());
}
try {
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->beginTransaction();
$dbh->exec("insert into staff (id, first, last) values (23, 'Joe', 'Bloggs')");
$dbh->exec("insert into salarychange (id, amount, changedate)
values (23, 50000, NOW())");
$dbh->commit();
} catch (Exception $e) {
$dbh->rollBack();
echo "Failed: " . $e->getMessage();
}
?>
Sie sind nicht darauf beschränkt, Änderungen in einer Transaktion durchzuführen. Sie
können auch komplexe Abfragen ausführen um Daten zu erhalten, und diese
Informationen etwa dazu benutzen, mehr Änderungen und Abfragen zu erzeugen. Während
die Transaktion aktiv ist, kann garantiert niemand anderes Änderungen durchführen,
während Sie bei der Arbeit sind. Um ehrlich zu sein, stimmt das nicht 100%, aber es
ist für den Anfang ausreichend, falls Sie noch nie von Transaktionen gehört haben.