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.

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

Web

Как заменить URL-адреса в тексте ссылками HTML

Как сделать слайдер в HTML на своем сайте: краткая инструкция
Web

Как сделать слайдер в HTML на своем сайте: краткая инструкция

Web

Как вставить новый элемент в массив в любую позицию на PHP

Самые полезные расширения для Google Chrome для веб-разработчика
Web

Самые полезные расширения для Google Chrome для веб-разработчика