Обработка транзакций в реальном мире - PullRequest
3 голосов
/ 09 декабря 2010

Я переписываю этот вопрос, потому что он не получил ответов.

Я пытаюсь найти правильный способ работы с транзакциями БД.Все, что я вижу о том, как выполнять транзакции, является очень простым, например:

  1. запрос "начать", чтобы начать транзакцию
  2. выполнить ваши запросы.
  3. , есливсе прошло нормально, зафиксируй транзакцию.

Я понял, но это обработка ошибок (тупиковых) я не получаю.Я слышал о двух вариантах:

  1. Показать пользователю ошибку и сказать «повторить попытку»
  2. Попробуйте еще раз, пока не получится.

Мне кажется, что говорить пользователю попробовать еще раз из-за такой технической проблемы кажется плохим - регулярно ли это делают реальные приложения?Это единственные ошибки типа "упс, что-то пошло не так", которые я иногда вижу?Это для веб-сайта, поэтому пользователи даже не должны знать о базе данных.

Поэтому у меня есть несколько вопросов:

  1. Какой подход к обработке ошибок следует использовать с данными, связанными снесколько пользователей одновременно?
  2. Если я выберу опцию «Instant Retry», что это повлечет за сложным сценарием PHP?Перезапустить весь запрос сверху?Я боюсь, что это вызовет больше проблем, чем решит.
  3. Есть ли третий вариант, который я не видел?

Ответы [ 3 ]

1 голос
/ 28 января 2011

Решение, которое я использую, заключается в создании цикла повторных попыток, скажем, 3 (я не думаю, что в реальной жизни большинства приложений я получаю более 1 повторной попытки). В этом цикле должен выполняться весь запрос транзакции, т.е. запрос на запись, а также запросы на чтение.

Одним очень важным моментом является выполнение там запросов внутри транзакции, так как это устанавливает блокировки, и это единственный способ получить данные на реальном уровне изоляции.

Тогда все эти запросы находятся в блоке begin / commit с try / catch. В секции catch я запускаю откат и перебрасываю исключение.

Повторно выбрасывая исключение, вы можете перехватить его на более высоком уровне, то есть на том уровне, на котором вы можете решить перезапустить (цикл 3 раза) или отправить его пользователю.

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

  • с использованием объектаactionManager, отвечающего за начало / принятие / отмена, все запросы в транзакции
  • получить правила, например, «все транзакции обрабатываются контроллерами, ни один объект уровня DAO или DB не знает, есть ли транзакция, запущенная
  • вы даже можете использовать выделенное соединение с базой данных (с правами на запись), которое используется только для TransactionManager, и сохранять исходное соединение с базой данных только для чтения для других целей.
0 голосов
/ 28 января 2011

Здесь есть пара вещей, которые вы не упомянули:

http://dev.mysql.com/doc/refman/5.0/en/innodb-deadlocks.html

0 голосов
/ 28 января 2011

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

В некоторых случаях это не будет проблемой, и вы попытаетесь повторить операцию, но я думаю, что в большинстве случаев вы сгенерируете ошибку для пользователя, поскольку вы знаете способ узнать, какое обновление было «правильным» один.

...