it-swarm.com.de

PHP + Beispiele für MySQL-Transaktionen

Ich habe wirklich kein normales Beispiel für PHP file gefunden, in dem MySQL-Transaktionen verwendet werden. Können Sie mir ein einfaches Beispiel dafür zeigen?

Und noch eine Frage. Ich habe bereits viel programmiert und keine Transaktionen verwendet. Kann ich eine PHP Funktion oder etwas in header.php dass, wenn man mysql_query scheitert, scheitern dann auch die anderen?


Ich denke, ich habe es herausgefunden, ist es richtig ?:

mysql_query("SET AUTOCOMMIT=0");
mysql_query("START TRANSACTION");

$a1 = mysql_query("INSERT INTO rarara (l_id) VALUES('1')");
$a2 = mysql_query("INSERT INTO rarara (l_id) VALUES('2')");

if ($a1 and $a2) {
    mysql_query("COMMIT");
} else {        
    mysql_query("ROLLBACK");
}
283
good_evening

Die Idee, die ich im Allgemeinen bei der Arbeit mit Transaktionen verwende, sieht folgendermaßen aus (Semi-Pseudo-Code) :

try {
    // First of all, let's begin a transaction
    $db->beginTransaction();

    // A set of queries; if one fails, an exception should be thrown
    $db->query('first query');
    $db->query('second query');
    $db->query('third query');

    // If we arrive here, it means that no exception was thrown
    // i.e. no query has failed, and we can commit the transaction
    $db->commit();
} catch (Exception $e) {
    // An exception has been thrown
    // We must rollback the transaction
    $db->rollback();
}


Beachten Sie, dass bei dieser Idee eine Ausnahme ausgelöst werden muss, wenn eine Abfrage fehlschlägt:

  • PDO kann das tun, je nachdem, wie Sie es konfigurieren
  • bei anderen APIs müssen Sie möglicherweise das Ergebnis der zum Ausführen einer Abfrage verwendeten Funktion testen und selbst eine Ausnahme auslösen.


Leider ist keine Magie involviert. Sie können nicht einfach irgendwo eine Anweisung platzieren und Transaktionen automatisch ausführen lassen: Sie müssen immer noch genau festlegen, welche Gruppe von Abfragen in einer Transaktion ausgeführt werden muss.

ZB haben Sie ziemlich oft ein paar Abfragen vor der Transaktion (vor dem begin) und ein paar Abfragen danach die Transaktion (entweder nach commit oder rollback) und Sie möchten, dass diese Abfragen ausgeführt werden, egal was passiert ist (oder nicht) in der Transaktion.

316
Pascal MARTIN

Ich denke, ich habe es herausgefunden, ist es richtig ?:

mysql_query("START TRANSACTION");

$a1 = mysql_query("INSERT INTO rarara (l_id) VALUES('1')");
$a2 = mysql_query("INSERT INTO rarara (l_id) VALUES('2')");

if ($a1 and $a2) {
    mysql_query("COMMIT");
} else {        
    mysql_query("ROLLBACK");
}
108
good_evening
<?php

// trans.php
function begin(){
    mysql_query("BEGIN");
}

function commit(){
    mysql_query("COMMIT");
}

function rollback(){
    mysql_query("ROLLBACK");
}

mysql_connect("localhost","Dude1", "SuperSecret") or die(mysql_error());

mysql_select_db("bedrock") or die(mysql_error());

$query = "INSERT INTO employee (ssn,name,phone) values ('123-45-6789','Matt','1-800-555-1212')";

begin(); // transaction begins

$result = mysql_query($query);

if(!$result){
    rollback(); // transaction rolls back
    echo "transaction rolled back";
    exit;
}else{
    commit(); // transaction is committed
    echo "Database transaction was successful";
}

?>
39
Gedzberg Alex

Da dies das erste Ergebnis auf Google für "php mysql transaction" ist, dachte ich, ich würde eine Antwort hinzufügen, die explizit demonstriert, wie dies mit mysqli gemacht wird (da der ursprüngliche Autor Beispiele wollte). Hier ist ein vereinfachtes Beispiel für Transaktionen mit PHP/mysqli:

// let's pretend that a user wants to create a new "group". we will do so
// while at the same time creating a "membership" for the group which
// consists solely of the user themselves (at first). accordingly, the group
// and membership records should be created together, or not at all.
// this sounds like a job for: TRANSACTIONS! (*cue music*)

$group_name = "The Thursday Thumpers";
$member_name = "EleventyOne";
$conn = new mysqli($db_Host,$db_user,$db_passwd,$db_name); // error-check this

// note: this is meant for InnoDB tables. won't work with MyISAM tables.

try {

    $conn->autocommit(FALSE); // i.e., start transaction

    // assume that the TABLE groups has an auto_increment id field
    $query = "INSERT INTO groups (name) ";
    $query .= "VALUES ('$group_name')";
    $result = $conn->query($query);
    if ( !$result ) {
        $result->free();
        throw new Exception($conn->error);
    }

    $group_id = $conn->insert_id; // last auto_inc id from *this* connection

    $query = "INSERT INTO group_membership (group_id,name) ";
    $query .= "VALUES ('$group_id','$member_name')";
    $result = $conn->query($query);
    if ( !$result ) {
        $result->free();
        throw new Exception($conn->error);
    }

    // our SQL queries have been successful. commit them
    // and go back to non-transaction mode.

    $conn->commit();
    $conn->autocommit(TRUE); // i.e., end transaction
}
catch ( Exception $e ) {

    // before rolling back the transaction, you'd want
    // to make sure that the exception was db-related
    $conn->rollback(); 
    $conn->autocommit(TRUE); // i.e., end transaction   
}

Denken Sie auch daran, dass PHP 5.5 eine neue Methode hat mysqli :: begin_transaction . Dies wurde jedoch noch nicht vom PHP - Team dokumentiert, und ich stecke immer noch in PHP 5.3 fest, sodass ich dazu keinen Kommentar abgeben kann.

35
EleventyOne

Bitte überprüfen Sie, welche Speicher-Engine Sie verwenden. Wenn es sich um MyISAM handelt, wird Transaction('COMMIT','ROLLBACK') nicht unterstützt, da nur die InnoDB-Speicher-Engine, nicht MyISAM, Transaktionen unterstützt.

8
dinesh

Bei Verwendung einer PDO-Verbindung:

$pdo = new PDO('mysql:Host=localhost;dbname=mydb;charset=utf8', $user, $pass, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // this is important
]);

Ich verwende häufig den folgenden Code für die Transaktionsverwaltung:

function transaction(Closure $callback)
{
    global $pdo; // let's assume our PDO connection is in a global var

    // start the transaction outside of the try block, because
    // you don't want to rollback a transaction that failed to start
    $pdo->beginTransaction(); 
    try
    {
        $callback();
        $pdo->commit(); 
    }
    catch (Exception $e) // it's better to replace this with Throwable on PHP 7+
    {
        $pdo->rollBack();
        throw $e; // we still have to complain about the exception
    }
}

Anwendungsbeispiel:

transaction(function()
{
    global $pdo;

    $pdo->query('first query');
    $pdo->query('second query');
    $pdo->query('third query');
});

Auf diese Weise wird der Transaktionsverwaltungscode nicht im gesamten Projekt dupliziert. Was gut ist, denn nach anderen gU-bewerteten Antworten in diesem Thread zu urteilen, ist es leicht, Fehler darin zu machen. Am häufigsten wird vergessen, die Ausnahme erneut auszulösen und die Transaktion innerhalb des Blocks try zu starten.

5
Danila Piatov

Ich habe eine Funktion erstellt, um einen Vektor von Abfragen abzurufen und eine Transaktion durchzuführen. Vielleicht findet jemand heraus, dass dies nützlich ist:

function transaction ($con, $Q){
        mysqli_query($con, "START TRANSACTION");

        for ($i = 0; $i < count ($Q); $i++){
            if (!mysqli_query ($con, $Q[$i])){
                echo 'Error! Info: <' . mysqli_error ($con) . '> Query: <' . $Q[$i] . '>';
                break;
            }   
        }

        if ($i == count ($Q)){
            mysqli_query($con, "COMMIT");
            return 1;
        }
        else {
            mysqli_query($con, "ROLLBACK");
            return 0;
        }
    }
5
Marco

Ich hatte das, aber nicht sicher, ob das richtig ist. Könnte das auch ausprobieren.

mysql_query("START TRANSACTION");
$flag = true;
$query = "INSERT INTO testing (myid) VALUES ('test')";

$query2 = "INSERT INTO testing2 (myid2) VALUES ('test2')";

$result = mysql_query($query) or trigger_error(mysql_error(), E_USER_ERROR);
if (!$result) {
$flag = false;
}

$result = mysql_query($query2) or trigger_error(mysql_error(), E_USER_ERROR);
if (!$result) {
$flag = false;
}

if ($flag) {
mysql_query("COMMIT");
} else {        
mysql_query("ROLLBACK");
}

Idee von hier: http://www.phpknowhow.com/mysql/transactions/

3
nodeffect

Noch ein prozedurales Beispiel mit mysqli_multi_query, geht davon aus $query ist mit durch Semikolons getrennten Anweisungen gefüllt.

mysqli_begin_transaction ($link);

for (mysqli_multi_query ($link, $query);
    mysqli_more_results ($link);
    mysqli_next_result ($link) );

! mysqli_errno ($link) ?
    mysqli_commit ($link) : mysqli_rollback ($link);
1
guest