PHP + MySQL transactions examples

后端 未结 9 2326
一整个雨季
一整个雨季 2020-11-21 11:50

I really haven\'t found normal example of PHP file where MySQL transactions are being used. Can you show me simple example of that?

And one more question. I\'ve alr

相关标签:
9条回答
  • 2020-11-21 12:00

    Please check which storage engine you are using. If it is MyISAM, then Transaction('COMMIT','ROLLBACK') will not be supported because only the InnoDB storage engine, not MyISAM, supports transactions.

    0 讨论(0)
  • 2020-11-21 12:04

    When using PDO connection:

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

    I often use the following code for transaction management:

    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
        }
    }
    

    Usage example:

    transaction(function()
    {
        global $pdo;
    
        $pdo->query('first query');
        $pdo->query('second query');
        $pdo->query('third query');
    });
    

    This way the transaction-management code is not duplicated across the project. Which is a good thing, because, judging from other PDO-ralated answers in this thread, it's easy to make mistakes in it. The most common ones being forgetting to rethrow the exception and starting the transaction inside the try block.

    0 讨论(0)
  • 2020-11-21 12:04

    I had this, but not sure if this is correct. Could try this out also.

    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");
    }
    

    Idea from here: http://www.phpknowhow.com/mysql/transactions/

    0 讨论(0)
  • 2020-11-21 12:06

    One more procedural style example with mysqli_multi_query, assumes $query is filled with semicolon-separated statements.

    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);
    
    0 讨论(0)
  • 2020-11-21 12:12

    I made a function to get a vector of queries and do a transaction, maybe someone will find out it useful:

    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;
            }
        }
    
    0 讨论(0)
  • 2020-11-21 12:14

    The idea I generally use when working with transactions looks like this (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 (\Throwable $e) {
        // An exception has been thrown
        // We must rollback the transaction
        $db->rollback();
        throw $e; // but the error must be handled anyway
    }
    

    Note that, with this idea, if a query fails, an Exception must be thrown:
    • PDO can do that, depending on how you configure it
      • See PDO::setAttribute
      • and PDO::ATTR_ERRMODE and PDO::ERRMODE_EXCEPTION
    • else, with some other API, you might have to test the result of the function used to execute a query, and throw an exception yourself.

    Unfortunately, there is no magic involved. You cannot just put an instruction somewhere and have transactions done automatically: you still have to specific which group of queries must be executed in a transaction.

    For example, quite often you'll have a couple of queries before the transaction (before the begin) and another couple of queries after the transaction (after either commit or rollback) and you'll want those queries executed no matter what happened (or not) in the transaction.

    0 讨论(0)
提交回复
热议问题