У меня есть некоторый (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 сохраняет ошибку вВ базе данных изменения будут отменены позже, и пользователь никогда не увидит сообщений об ошибках.
Существует два простых решения, которые я вижу:
- Измените мой код так, чтобы
messageSystem
вызывается вне транзакции.Тем не менее, это более читабельно и быстрее писать, если я могу сделать это встроенным, как указано выше.Кроме того, что, если это библиотечный код, который может быть уже во вложенной транзакции? - Изменить
messageSystem
, чтобы он использовал свое собственное соединение с базой данных.Но что, если я сделаю messageSystem более сложным и решу, что ему нужно заблокировать запись в таблице session
, прежде чем она добавит сообщения в этот сеанс.Это может привести к тупиковой ситуации, если мой основной код также по какой-либо причине заблокировал сеанс. - Проверка на наличие ошибок перед транзакцией.Но на самом деле мне нужно заблокировать соответствующие строки, выбрав «FOR UPDATE» до . Я могу проверить ввод.
И поэтому мой вопрос: есть ли способпередайте X, когда он находится внутри (возможно, вложенной) транзакции, так что если откат транзакции будет выполнен, X все равно будет зафиксирован.
В качестве альтернативы есть какой-либо хороший способ избежать описанной мной проблемы.
Спасибо!