Ответ 1
Сбой транзакции. "Тупик" - это случай неудачи, и вы можете получить больше сбоев в сериализуемых уровнях. Проблемы изоляции транзакций - это кошмар. Попытка избежать неудач - плохой способ, я думаю.
Я думаю, что любой хорошо написанный код транзакции должен быть эффективно подготовлен к сбою транзакций.
Поскольку вы видели записи запросов и повторное воспроизведение их не является решением, как при перезагрузке транзакции база данных переместилась. Если бы это было правильное решение, SQL-движок наверняка сделает это за вас. Для меня правила:
- повторите все ваши чтения внутри транзакций (любые данные, которые вы прочитали снаружи, возможно, были изменены)
- бросить все от предыдущей попытки, если вы пишете вещи за пределами транзакции (журналы, LDAP, что-либо вне SGBD), ее следует отменить из-за отката
- повторить все на самом деле :-)
Это означает цикл повтора.
Таким образом, у вас есть блок try/catch с транзакцией внутри. Вам нужно добавить while
цикл с, может быть, 3 попытки, вы оставите время цикла, если совершить часть кода успеха. Если после 3 повторных попыток транзакция все еще терпит неудачу, запустите Exception для пользователя - чтобы вы не пытались использовать замкнутый цикл повтора, у вас может быть действительно большая проблема на самом деле. Обратите внимание, что вы должны обрабатывать SQL-ошибку и блокировать или сериализовать исключение по-разному. 3 - произвольное число, вы можете попробовать большее количество попыток.
Это может дать что-то вроде этого:
$retry=0;
$notdone=TRUE;
while( $notdone && $retry<3 ) {
try {
$transaction->begin();
do_all_the_transaction_stuff();
$transaction->commit();
$notdone=FALSE;
} catch( Exception $e ) {
// here we could differentiate basic SQL errors and deadlock/serializable errors
$transaction->rollback();
undo_all_non_datatbase_stuff();
$retry++;
}
}
if( 3 == $retry ) {
throw new Exception("Try later, sorry, too much guys other there, or it not your day.");
}
И это означает, что все вещи (читая, записывая, fonctionnal вещи) должны быть заключены в $do_all_the_transaction_stuff();
, Предполагая, что код управления транзакциями находится в контроллерах, основной код с высоким уровнем приложения, а не разделен на несколько объектов с низким уровнем доступа к базе данных.