Bryan Albrecht

MySQLI Transactions

Als erste möchte ich kurz erklären, was Transaktionen sind:
Transaktionen werden verwendet, wenn sichergestellt werden muss, dass mehrere Statements hintereinander korrekt ausgeführt werden. Das heisst, wenn 100 Statements in einer Transaktion ausgeführt werden und nur eines davon fehlerhaft ist, dass dann alle restlichen 99 rückgängig gemacht werden.
Dies ist machbar, da manchmal mehrere Statements zusammengehören und nicht einzeln ausgeführt werden dürfe/sollen.

Ein gutes Beispiel dafür ist eine Banküberweisung: Bei einer Banküberweisung müssen jeweils zwei Statements hintereinander bzw. zusammen ausgeführt werden.
Eines der beiden Statements hebt das Geld auf Konto 1 ab und das zweite Statement für es dem Konto 2 hinzu.
Wenn jetzt das Abheben klappen würde, aber das Hinzufügen nicht, gäbe es einen enormen Geldverlust. Aus diesem Grund wird das erste Statement in diesem Fall rückgängig gemacht.

MySQLI bietet die Möglichkeit eine Transaktion durchzuführen. Diesen Vorgang erkläre ich in diesen Tutorial.

Datenbank:

Um mit Transaktionen arbeiten zu können, brauchen wir als erstes eine Datenbank. Mit den folgenden Statements erstell ich eine Tabelle, welche zwei verschiedene "Konten" beinhaltet.

  1. CREATE TABLE tbl_konten (
  2. `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  3. account_name VARCHAR(45) NOT NULL,
  4. account_value DECIMAL NOT NULL
  5. )ENGINE=INNODB;
  1. INSERT INTO `tbl_konten` (`account_name`, `account_value`) VALUES (Grace,'1000');
  2. INSERT INTO `tbl_konten` (`account_name`, `account_value`) VALUES ('Peter','30000');

Ausgangslage:

Nehmen wir an, dass Peter Grace 4'000 Fr. Überweisen möchten.
Aus diesem Grund wird der neue Kontostand von Grace 5'000 Fr. und der von Peter 26'000 Fr. sein.
Dies wird mit folgenden Statements gemacht:

  1. UPDATE tbl_konten SET account_value = '26000' WHERE account_name = 'Peter';
  2. UPDATE tbl_konten SET account_value = '5000' WHERE account_name = 'Grace';

Transaktionen:

Die beiden UPDATE Statements sollen nun in eine Transaktion verpackt werden, da sonst 4'000 Fr. verloren gehen könnten.

Als erstes muss mit MySQLI eine Datenbankverbindung aufgebaut werden:

  1. $dbConnection = mysqli_connect('localhost', 'root', '', 'konten_db');

Als nächstes soll das automatische "Commiten " ausgeschaltet werden und das Error-Falg auf "false" gesetzt werden:

  1. mysqli_autocommit($dbConnection, false);
  2. $consistsAnError = false;

Da nun alles vorbereitet ist, können die beiden Statements hinzugefügt werden.

  1. $statementOne = " UPDATE tbl_konten SET account_value = '26000' WHERE account_name = 'Peter'";
  2. $statementTwo = " UPDATE tbl_konten SET account_value = '5000' WHERE account_name = 'Grace'";

Die beiden Statements werden nun ausgeführt und auf Fehler überprüft:

  1. $queryResult = mysqli_query($dbConnection, $query1);
  2. if (!$queryResult) {
  3.     $ consistsAnError = true;
  4.     echo "Error: " . mysqli_error($dbConnection) . ".";
  5. }
  6. $queryResult = mysqli_query($dbConnection, $query2);
  7. if (!$queryResult) {
  8.     $ consistsAnError = true;
  9.     echo "Error: " . mysqli_error($dbConnection) . ".";
  10. }

Nach dem nun die Statements ausgeführt wurden und auf Fehler geprüft wurden, ist es an der Zeit zu entscheiden, ob die Änderungen beibehalten werden dürfen.

Wenn Alles gut ging, werden die Änderungen "Commitet" und sonst wird ein Rollback gemacht:

  1. if ($consistsAnError) {
  2.     mysqli_rollback($dbConnection);
  3.     echo "Alles wurde rückgängig gemacht.";
  4. } else {
  5.     mysqli_commit($dbConnection);
  6.     echo "Änderungen wurden erfolgreiche gespeichert";
  7. }

Da nun alle Aktionen gemacht wurden, welche mit der Datenbank zu tun haben, kann die Datenbankverbindung geschlossen werden:

  1. mysqli_close($dbConnection);

Kompletter Code:

  1. $dbConnection = mysqli_connect('localhost', 'root', '', 'konten_db');
  2. mysqli_autocommit($dbConnection, false);
  3. $consistsAnError = false;
  4.  
  5. $statementOne = " UPDATE tbl_konten SET account_value = '26000' WHERE account_name = 'Peter'";
  6. $statementTwo = " UPDATE tbl_konten SET account_value = '5000' WHERE account_name = 'Grace'";
  7.  
  8. $queryResult = mysqli_query($dbConnection, $query1);
  9. if (!$queryResult) {
  10.     $ consistsAnError = true;
  11.     echo "Error: " . mysqli_error($dbConnection) . ".";
  12. }
  13.  
  14. $queryResult = mysqli_query($dbConnection, $query2);
  15. if (!$queryResult) {
  16.     $ consistsAnError = true;
  17.     echo "Error: " . mysqli_error($dbConnection) . ".";
  18. }
  19.  
  20. if ($consistsAnError) {
  21.     mysqli_rollback($dbConnection);
  22.     echo "Alles wurde rückgängig gemacht.";
  23. } else {
  24.     mysqli_commit($dbConnection);
  25.     echo "Änderungen wurden erfolgreiche gespeichert";
  26. }
  27.  
  28. mysqli_close($dbConnection);