首页 文章

PHP MySQL事务示例

提问于
浏览
275

我真的没有找到正在使用MySQL事务的PHP文件的正常示例 . 你能告诉我一个简单的例子吗?

还有一个问题 . 我've already done a lot of programming and didn' t使用交易 . 我可以在 header.php 中放一个PHP函数,如果一个_656202失败,那么其他人也会失败吗?


我想我已经弄清楚了,是不是?:

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

9 回答

  • 304

    我在处理事务时通常使用的想法如下(半伪代码):

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

    请注意,有了这个想法,如果查询失败,则必须抛出异常:

    • PDO可以这样做,具体取决于您的配置方式

    • PDO::setAttribute

    • PDO::ATTR_ERRMODEPDO::ERRMODE_EXCEPTION

    • else,使用其他API,您可能必须测试用于执行查询的函数的结果,并自己抛出异常 .

    不幸的是,没有任何魔法涉及 . 您不能只是在某处放置指令并自动完成事务:您仍然必须具体必须在事务中执行哪组查询 .

    例如,在事务之前(在 begin 之前)和事务之后的另外几个查询(在 commitrollback 之后),您经常会有几个查询,并且无论发生什么事情,您都希望执行这些查询(或者不)在交易中 .

  • 106

    我想我已经弄清楚了,是不是?:

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

    由于这是google上“php mysql transaction”的第一个结果,我想我会添加一个明确演示如何使用mysqli进行此操作的答案(正如原作者想要的例子) . 这是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   
    }
    

    另外,请记住PHP 5.5有一个新方法mysqli::begin_transaction . 但是,PHP团队尚未对此进行记录,我对此进行了评论 .

  • 5

    请检查您使用的存储引擎 . 如果它是MyISAM,则不支持 Transaction('COMMIT','ROLLBACK') ,因为只有InnoDB存储引擎而不是MyISAM支持事务 .

  • 3

    我创建了一个函数来获取查询向量并执行事务,也许有人会发现它很有用:

    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

    使用PDO连接时:

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

    我经常使用以下代码进行事务管理:

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

    用法示例:

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

    这样,事务管理代码不会在整个项目中重复 . 这是一件好事,因为从这个帖子中的其他PDO相关答案判断,很容易在其中犯错误 . 最常见的是忘记重新抛出异常并在 try 块内启动事务 .

  • 37

    我有这个,但不确定这是否正确 . 也可以尝试一下 .

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

    来自这里的想法:http://www.phpknowhow.com/mysql/transactions/

  • 1

    使用 mysqli_multi_query 的另一个程序样式示例假设 $query 填充了以分号分隔的语句 .

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

相关问题