Intereting Posts
Youtube API (PHP) – как добавить (существующее) видео в существующий плейлист? HTTP if-none-match и if-modified-since и 304 разъяснение в PHP Обновление данных без удаления старых файлов с кодом CodeIgniter Ошибка «Нет данных», когда у меня есть запрос mysql во время цикла Быстрая функция для замены «с помощью» в php Получить текущий ключ массива внутри foreach Как отложить или аскетировать этот фрагмент javascript WordPress, чтобы загрузить последний раз для более быстрого времени загрузки страницы? Laravel orderBy дата не работает при использовании paginator CodeIgniter Две таблицы Left Join не возвращает идентификатор условия соединения левой таблицы при пропуске в правой таблице переместить все файлы и папки в папку на другую? URL-адрес, скрытый в PHP CodeIgniter Неустранимая ошибка: допустимый объем памяти байтов Экспорт таблицы HTML в csv в браузере Chrome Chrome Импортировать проект laravel 4.2 в eclipse Запретить знак доллара из определенных строк

Примеры транзакций PHP + MySQL

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

И еще один вопрос. Я уже много программировал и не использовал транзакции. Могу ли я поместить функцию PHP или что-то в header.php , если один из mysql_query терпит неудачу, то остальные тоже не 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"); } 

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

 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 // ie 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_ERRMODE и PDO::ERRMODE_EXCEPTION
  • иначе, с каким-либо другим API, вам, возможно, придется проверить результат функции, используемой для выполнения запроса, и самостоятельно выбросить исключение.

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

Например, довольно часто у вас будет несколько запросов перед транзакцией (до 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"; } ?> 

Поскольку это первый результат в google для «транзакции php mysql», я подумал, что добавлю ответ, который явно демонстрирует, как это сделать с помощью 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); // ie, 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); // ie, 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); // ie, end transaction } 

Кроме того, имейте в виду, что PHP 5.5 имеет новый метод mysqli :: begin_transaction . Однако это еще не задокументировано командой PHP, и я все еще придерживаюсь PHP 5.3, поэтому я не могу прокомментировать это.

Проверьте, какой механизм хранения вы используете. Если это MyISAM, Transaction('COMMIT','ROLLBACK') не будет поддерживаться, потому что только транзакция InnoDB, а не MyISAM, поддерживает транзакции.

Я сделал функцию, чтобы получить вектор запросов и выполнить транзакцию, может быть, кто-то найдет ее полезной:

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

У меня было это, но не уверен, что это правильно. Мог бы попробовать это тоже.

 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/

При использовании 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 .

Еще один пример процедурного стиля с 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);