[php] PHP + MySQL 트랜잭션 예제

MySQL 트랜잭션이 사용되는 PHP 파일의 일반적인 예를 찾지 못했습니다. 간단한 예를 보여 주시겠습니까?

그리고 하나 더 질문. 나는 이미 많은 프로그래밍을 수행했으며 트랜잭션을 사용하지 않았습니다. header.php하나 mysql_query가 실패하면 다른 하나도 실패 하는 PHP 함수 또는 다른 것을 넣을 수 있습니까 ?


나는 그것을 이해했다고 생각한다, 맞습니까? :

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



답변

트랜잭션 작업을 할 때 일반적으로 사용하는 아이디어는 다음과 같습니다 (세미 의사 코드) .

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가이를 수행 할 수 있습니다.
  • 그렇지 않으면 다른 API를 사용하여 쿼리를 실행하는 데 사용 된 함수의 결과를 테스트하고 예외를 직접 throw해야 할 수도 있습니다.

불행히도 관련된 마술은 없습니다. 어딘가에 지시를 내릴 수 없으며 트랜잭션을 자동으로 수행 할 수 있습니다. 트랜잭션에서 실행해야하는 쿼리 그룹을 구체적으로 지정해야합니다.

예를 들어, 매우 자주 거래하기 전에 쿼리의 몇 가지를해야 합니다 (이전 begin) 및 거래 후 쿼리의 또 다른 커플 (중 후 commit또는 rollback) 그 쿼리에 무슨 일이 있었는지에 상관없이 실행하고 당신이 원하는 것 (여부) 에 거래.


답변

나는 그것을 이해했다고 생각한다, 맞습니까? :

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


답변

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

?>


답변

이것이 “php mysql transaction”에 대한 Google의 첫 번째 결과이므로, 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 팀에 의해 문서화되지 않았으며 여전히 PHP 5.3에 갇혀 있으므로 주석을 달 수 없습니다.


답변

사용중인 스토리지 엔진을 확인하십시오. MyISAM 인 경우 MyISAM Transaction('COMMIT','ROLLBACK')이 아닌 InnoDB 스토리지 엔진 만 트랜잭션을 지원하므로 지원되지 않습니다.


답변

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블록 내에서 트랜잭션을 시작하는 것 입니다.


답변

쿼리 벡터를 얻고 트랜잭션을 수행하는 함수를 만들었습니다. 어쩌면 누군가가 유용하다는 것을 알 수 있습니다.

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