Могу ли я обойти текущую транзакцию в MySQL? - PullRequest
2 голосов
/ 20 июля 2011

У меня есть некоторый (php) код, который выполняет критические обновления таблицы InnoDB.

Я использую (SELECT ... FOR UPDATE), поэтому мне нужно быть внутри транзакции.

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

Некоторый псевдокод: (я пропускаю такие вещи, как блоки try / catch и экранирование, которые есть в моем реальном коде)

beginTransaction();

query("SELECT * FROM `table` WHERE id=1 FOR UPDATE");

$x=$_POST[$x];
query("UPDATE `table` SET `field` = $X");

//add other data in the db related to $X
query("INSERT INTO `othertable` (x,y,x) VALUES (......)");


//check for various errors...
$erros=0

if ($error_condition_1) {
    messageSystem("Error Condition 1!")
    $errors+=1;
}
if ($error_condition_2) {
    messageSystem("Error Condition 2!")
    $errors+=1;
}

if ($errors) {
    rollBackTransaction();
} else {
    commitTransaction();
}

Проблема должна быть очевидной: когда messageSystem сохраняет ошибку вВ базе данных изменения будут отменены позже, и пользователь никогда не увидит сообщений об ошибках.

Существует два простых решения, которые я вижу:

  1. Измените мой код так, чтобы messageSystem вызывается вне транзакции.Тем не менее, это более читабельно и быстрее писать, если я могу сделать это встроенным, как указано выше.Кроме того, что, если это библиотечный код, который может быть уже во вложенной транзакции?
  2. Изменить messageSystem, чтобы он использовал свое собственное соединение с базой данных.Но что, если я сделаю messageSystem более сложным и решу, что ему нужно заблокировать запись в таблице session, прежде чем она добавит сообщения в этот сеанс.Это может привести к тупиковой ситуации, если мой основной код также по какой-либо причине заблокировал сеанс.
  3. Проверка на наличие ошибок перед транзакцией.Но на самом деле мне нужно заблокировать соответствующие строки, выбрав «FOR UPDATE» до . Я могу проверить ввод.

И поэтому мой вопрос: есть ли способпередайте X, когда он находится внутри (возможно, вложенной) транзакции, так что если откат транзакции будет выполнен, X все равно будет зафиксирован.

В качестве альтернативы есть какой-либо хороший способ избежать описанной мной проблемы.

Спасибо!

1 Ответ

2 голосов
/ 20 июля 2011

Простой ответ - использовать второе соединение с базой данных для регистрации ошибок.

...