Wie starte und beende ich eine Transaktion in mysqli?

Lesezeit: 8 Minuten

Wie starte und beende ich eine Transaktion in mysqli
Bachtiyor

Soweit ich verstanden habe, beginnt die Transaktion, sobald wir anrufen $mysqli->autocommit(FALSE); Anweisung und endet nach dem Aufruf $mysqli->commit(); Befehl wie im Beispiel unten.

<?php
//Start transaction 
$mysqli->autocommit(FALSE);
$mysqli->query('UPDATE `table` SET `col`=2');
$mysqli->query('UPDATE `table1` SET `col1`=3;');
$mysqli->commit();
//End transaction

//Executing other queries without transaction control
$mysqli->query("Select * from table1");
$mysqli->query("Update table1 set col1=2");
//End of executing other queries without transaction control

//Start transaction 
$mysqli->autocommit(FALSE);
$mysqli->query('UPDATE `table` SET `col`=2');
$mysqli->query('UPDATE `table1` SET `col1`=3;');
$mysqli->commit();
//End transaction
?>

Habe ich richtig verstanden? Wenn nicht, könnten Sie mich bitte korrigieren, da ich tatsächlich zum ersten Mal Transaktionen im wirklichen Leben verwende.

Danke.

Wie starte und beende ich eine Transaktion in mysqli
j0k

Update November 2020: @Dharman gab eine bessere Antwort mit mehr Details zu Transaktionen in mysqli, überprüfen Sie es stattdessen einfach: https://stackoverflow.com/a/63764001/569101 👇


Naja laut das php-docDu hast recht.

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$mysqli->query("CREATE TABLE Language LIKE CountryLanguage");

/* set autocommit to off */
$mysqli->autocommit(FALSE);

/* Insert some values */
$mysqli->query("INSERT INTO Language VALUES ('DEU', 'Bavarian', 'F', 11.2)");
$mysqli->query("INSERT INTO Language VALUES ('DEU', 'Swabian', 'F', 9.4)");

/* commit transaction */
$mysqli->commit();

/* drop table */
$mysqli->query("DROP TABLE Language");

/* close connection */
$mysqli->close();
?>

Im obigen Beispiel:

  • der CREATE TABLE wird automatisch festgeschrieben, da dies das Standardverhalten ist.
  • der INSERT INTO sind nicht Auto begangen wegen der autocommit(FALSE).
  • der DROP TABLE wird automatisch festgeschrieben, weil die autocommit(FALSE) war zurücksetzen bis zum ->commit();.

  • Per @Patec unten: Commit schaltet Autocommit NICHT wieder ein; siehe die Quelle

    – Erwin Wessels

    8. Mai 2013 um 12:39 Uhr

  • Ich weiß, dass Sie diese Antwort nicht entfernen können, aber ich möchte Sie höflich bitten, sie erneut zu überprüfen und zu verbessern. Die PHP-Handbuchseite, die Sie kopiert haben, enthielt ein fehlerhaftes Beispiel, das nicht zeigte, wie Transaktionen richtig verwendet werden. Diese Seite wurde nun entfernt und ein neues Beispiel bereitgestellt. Da Ihre Antwort die akzeptierte ist, zeichnet sie ein Bild, dass dies die richtige Lösung ist, aber sie ist es nicht. Bitte, wenn Sie könnten, könnten Sie es verbessern?

    – Dharman

    17. November 2020 um 22:32 Uhr

  • Wow ziemlich alte Antwort. Ich sehe, dass Ihre Antwort besser ist, und ich habe keine Zeit, meine eigene Antwort zu verbessern. Also habe ich meine Antwort bearbeitet, um auf Ihre Antwort zu verlinken.

    – j0k

    18. November 2020 um 13:28 Uhr

1646628851 637 Wie starte und beende ich eine Transaktion in mysqli
Bolowski

j0k hat größtenteils Recht, außer in der Drop-Tabelle.

Der Auto-Commit wird mit dem nicht eingeschaltet ->commit()

Stattdessen ist die DROP TABLE eine DDL-Abfrage, und DDL-Abfragen werden immer implizit festgeschrieben und werden Ihre gesamte zuvor nicht festgeschriebene Arbeit festschreiben.

Wenn Sie also die Arbeit nicht festgeschrieben haben, würde die DDL-Abfrage diese Festschreibung erzwingen.

  • Für diejenigen, die sich fragen: DDL bedeutet Datendefinitionssprache. Sehen Dieser Beitrag für den Unterschied zwischen DDL, DQL, DML, DCL und TCL.

    – Achtsam

    29. Oktober 2019 um 16:34 Uhr


  • @Minding Ich hätte diese Perle wahrscheinlich vor ein paar Jahren anbieten sollen. Das hätte ich auch angeben sollen $mysqli->commit(); schaltet Auto-Commits nicht auf magische Weise ein. Nun, vor 6 Jahren haben wir gelernt, dass wir noch ein paar Dinge beantworten sollten 🙂

    – Bolowski

    4. Dezember 2019 um 16:37 Uhr

1646628852 191 Wie starte und beende ich eine Transaktion in mysqli
Dharman

Wie verwendet man Transaktionen in mysqli?

Voraussetzung

Damit sich die Transaktionen ordnungsgemäß verhalten, sollten Sie die Ausnahmefehlerberichterstattung aktivieren. Andernfalls meldet mysqli keine Fehler und die Transaktion wird nicht korrekt ausgeführt. Alternativ könnten Sie jede Abfrage manuell überprüfen, aber das wird nicht empfohlen. Verwenden Sie die folgenden 3 Zeilen, um eine ordnungsgemäße Verbindung mit mysqli herzustellen:

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'user', 'pass', 'dbname');
$mysqli->set_charset('utf8mb4'); // always set the charset

Transaktionen funktionieren nur mit Transaktionstabellen. Stellen Sie sicher, dass Ihre Tabellenspeicher-Engine Transaktionen unterstützt. Zum Beispiel ignoriert MyISAM den Commit/Rollback.

Transaktionen

Es gibt zwei Möglichkeiten, eine Transaktion mit mysqli zu erstellen. Standardmäßig werden alle Abfragen/Anweisungen festgeschrieben, sobald sie ausgeführt werden. Sie können Autocommit entweder ausschalten oder eine einmalige Transaktion verwenden.

Transaktionen werden in den folgenden Situationen an die Datenbank übertragen:

  • beim Anrufen commit
  • nach dem Setzen von autocommit=1
  • beim Starten einer anderen Transaktion
  • beim Durchführen einer DDL-Abfrage
  • und in einigen anderen Situationen. Weitere Informationen finden Sie unter Anweisungen, die ein implizites Commit verursachen

Verwenden von Autocommit (false)

Wenn Sie Autocommit ausschalten, entscheiden Sie, wann Sie ein Commit durchführen möchten, rufen aber auf commit() schaltet Autocommit nicht wieder ein.

//Start transaction
$mysqli->autocommit(false);

$mysqli->query('INSERT INTO director(name) VALUE("Steven Spielberg")');

$directorId = $mysqli->insert_id;
$movieTitle="Jurassic Park";
$stmt = $mysqli->prepare('INSERT INTO movie(title, directorId) VALUE(?,?)');
$stmt->bind_param('ss', $movieTitle, $directorId);
$stmt->execute();

$mysqli->commit();
// Changes are committed, but autocommit is not switched back on

// Following queries are still transactional.
// They will not be committed unless you call commit or switch autocommit back on
$mysqli->query('INSERT INTO director(name) VALUE("James Cameron")');

$directorId = $mysqli->insert_id;
$movieTitle="Titanic";
$stmt = $mysqli->prepare('INSERT INTO movie(title, directorId) VALUE(?,?)');
$stmt->bind_param('ss', $movieTitle, $directorId);
$stmt->execute();

$mysqli->autocommit(true);
// All queries are committed and everything that follows will be immediately committed.

Verwendung von begin_transaction()

Sie können eine einmalige Transaktion mit starten begin_transaction(). Dies wird nicht eingestellt autocommit=false also wenn du anrufst commit() Sie beenden die Transaktion, ohne eine neue zu beginnen.

//Start transaction 
$mysqli->begin_transaction();

$mysqli->query('INSERT INTO director(name) VALUE("Steven Spielberg")');

$directorId = $mysqli->insert_id;
$movieTitle="Jurassic Park";
$stmt = $mysqli->prepare('INSERT INTO movie(title, directorId) VALUE(?,?)');
$stmt->bind_param('ss', $movieTitle, $directorId);
$stmt->execute();

$mysqli->commit();
// Changes are committed and the transaction has ended

// Following queries will be committed one by one as soon as they are peformed.
$mysqli->query('INSERT INTO director(name) VALUE("James Cameron")');

$directorId = $mysqli->insert_id;
$movieTitle="Titanic";
$stmt = $mysqli->prepare('INSERT INTO movie(title, directorId) VALUE(?,?)');
$stmt->bind_param('ss', $movieTitle, $directorId);
$stmt->execute();

Ausführen von DDL-Anweisungen

Einige SQL-Anweisungen lösen einen expliziten Commit aus, wirken sich aber nicht auf den Wert von aus autocommit.

//Start transaction 
$mysqli->autocommit(false);

$mysqli->query('INSERT INTO director(name) VALUE("Steven Spielberg")');

$directorId = $mysqli->insert_id;
$movieTitle="Jurassic Park";
$stmt = $mysqli->prepare('INSERT INTO movie(title, directorId) VALUE(?,?)');
$stmt->bind_param('ss', $movieTitle, $directorId);
$stmt->execute();

// The following will call commit but it will not set autocommit=true
$mysqli->query('TRUNCATE TABLE movie_genre');
// if you want to switch autocommit back on, you have to call: 
$mysqli->autocommit(true);

Zurücksetzen

Wenn eine Ausnahme auftritt, beendet PHP die Ausführung des Skripts und der Code erreicht nie die commit Aussage. In einigen Situationen möchten Sie die Transaktion jedoch möglicherweise explizit zurücksetzen, um beispielsweise zu vermeiden, dass commit versehentlich an einer anderen Stelle im Code aufgerufen wird.

Hier ist ein Beispiel dafür, wie eine solche Transaktion aussehen würde. Die zweite Abfrage versucht, in eine nicht vorhandene Tabelle einzufügen, was bedeutet, dass mysqli eine Ausnahme auslöst. Anstatt das PHP-Skript sterben zu lassen, fangen wir die Ausnahme ab und machen die Transaktion rückgängig. Der Wert 4 wird nie in die Datenbank eingefügt, da beide Abfragen rückgängig gemacht wurden.

try {
    // Start transaction
    $mysqli->begin_transaction();

    $mysqli->query('INSERT INTO some_table(col2) VALUE(4)');
    $mysqli->query('INSERT INTO does_not_exist(col2) VALUE(4)');

    // Commit changes
    $mysqli->commit();
} catch (\Throwable $e) {
    // Something went wrong. Rollback
    $mysqli->rollback();
    // Rethrow the exception so that PHP does not continue
    // with the execution and the error can be logged in the error_log
    throw $e;
}

  • Ihre Beispiele hier bzgl begin_transaction() Kann verbessert werden; Wenn jemand dieselben Daten zweimal in eine Tabelle einfügt, möchte er höchstwahrscheinlich, dass diese Daten einmal erscheinen, anstatt eine Transaktion zu verwenden, um sie null Mal erscheinen zu lassen. Der Sinn von MySQL-Transaktionen besteht darin, dass sie gültige Aktualisierungen zurücksetzen, wenn eine verknüpfte Aktualisierung fehlschlägt. Das einfache Duplizieren einer SQL-Einfügung spiegelt dies nicht wider.

    – Martin

    16. November 2020 um 16:26 Uhr


  • @Martin Ich bin ehrlich, ich glaube nicht, dass ich Ihren Kommentar vollständig verstehe, aber ich würde die Antwort gerne verbessern, wenn es möglich ist. Ich habe eine kleine Änderung am letzten Beispiel vorgenommen, um deutlicher zu zeigen, welche Abfrage fehlschlägt. Wenn Sie Ihren Vorschlag vielleicht etwas näher erläutern könnten, wäre ich Ihnen dankbar.

    – Dharman

    16. November 2020 um 23:18 Uhr

  • Der Zweck von Transaktionen ist wirklich für “Gruppen” von einzelnen gültigen SQL-Aktionen; zum Beispiel Erstellen einer Bestellung durch Füllen einer Bestellkorbtabelle und einer Bestellhaupttabelle. Daher kann es sinnvoller sein, einfügen in zu haben movie table einen gültigen Film, wobei eine andere Spalte auf eine Filmproduzententabelle verweist, wobei der Name/Geburtstag des Produzenten usw. ungültig ist, sodass der Film nicht hinzugefügt wird, wenn der Produzent des Films ungültig ist. Nur eine Idee, da dieses Thema (Beispielfälle aus dem wirklichen Leben, in denen Transaktionen nützlich sind) schwer zu finden ist, praktische Beispiele zu finden.

    – Martin

    17. November 2020 um 9:42 Uhr


1646628853 338 Wie starte und beende ich eine Transaktion in mysqli
Patec

Du denkst das commit schaltet automatisch um autocommit zurück zu true? Ein Kommentar in der PHP-Dokument sagt NEIN!

962930cookie-checkWie starte und beende ich eine Transaktion in mysqli?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy