Web

Транзакции в PHP + MySQL

Я не нашел нормального примера PHP-файла, в котором используются транзакции MySQL. Вы можете показать мне простой пример?

И еще один вопрос. Я уже много программировал и не использовал транзакции. Могу ли я поместить PHP-функцию или что-то в header.php, чтобы если один mysql_query не сработает, то и остальные тоже?

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

}

 

Ответ 1

Идея, которую я обычно использую при работе с транзакциями, выглядит так (полу-псевдокод):

try {

    // Прежде всего давайте запустим транзакцию

    $db->beginTransaction();

    // Набор запросов; если один из них не работает, должно быть выброшено исключение

    $db->query('first query');

    $db->query('second query');

    $db->query('third query');

    // Если мы дошли до этого места, это означает, что исключение не возникло

    // т. е. ни один запрос не завершился неудачей, и мы можем зафиксировать транзакцию

    $db->commit();

} catch (\Throwable $e) {

    // Возникло исключение

    // Мы должны откатить транзакцию

    $db->rollback();

    throw $e; // но ошибка должна быть обработана в любом случае

}


Обратите внимание, что с этой идеей, если запрос не выполняется, должно быть сгенерировано исключение:

  • PDO может это сделать, в зависимости от того, как вы его настраиваете;

  • иначе, с каким-либо другим API, вам, возможно, придется протестировать результат функции, используемой для выполнения запроса, и самостоятельно выбросить исключение.


Вы не можете просто поместить где-то инструкцию и выполнять транзакции автоматически: вам все равно нужно указать, какая группа запросов должна быть выполнена в транзакции.

Например, довольно часто у вас будет пара запросов перед транзакцией (до begin) и еще пара запросов после транзакции (после любого commit или rollback), и вы захотите, чтобы эти запросы выполнялись независимо от того, как выполнялся скрипт до этого.

 

Ответ 2

// 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(); //запуск транзакции

$result = mysql_query($query);

if(!$result){

    rollback();

    echo "Откат транзакции";

    exit;

}else{

    commit();

    echo "Транзакция выполнена успешно";

}

?>

 

Ответ 3

Я подумал, что добавлю ответ, который явно демонстрирует, как это сделать с помощью mysqli. Вот упрощенный пример транзакций с PHP/mysqli:

// представим, что пользователь хочет создать новую "группу". мы сделаем это.

// и одновременно создадим "членство" в группе, которое

// состоит исключительно из самого пользователя (вначале). соответственно, записи о группе

// и записи о членстве должны быть созданы вместе или не создаваться вообще.

$group_name     = "The Thursday Thumpers";

$member_name = "EleventyOne";

$conn = new mysqli($db_host,$db_user,$db_passwd,$db_name); 

// примечание: это предназначено для таблиц InnoDB. не будет работать с таблицами MyISAM.

try {

    $conn->autocommit(FALSE); // запуск транзакции

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

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

    }

    $conn->commit();

    $conn->autocommit(TRUE); }

catch ( Exception $e ) {

    $conn->rollback(); 

    $conn->autocommit(TRUE);

 }

 

Также имейте в виду, что в PHP 5.5 есть новый метод mysqli::begin_transaction.

Схожие статьи

ТОП-100 паролей сети: лучшие из лучших, худшие из худших
Web

ТОП-100 паролей сети: лучшие из лучших, худшие из худших

Web

Как проверить, является ли массив PHP ассоциативным или последовательным

Web

Как получить значения функции при вводе значения из PHP формы?

Web

Как использовать XMLReader в PHP