Решение, которое я использую, заключается в создании цикла повторных попыток, скажем, 3 (я не думаю, что в реальной жизни большинства приложений я получаю более 1 повторной попытки). В этом цикле должен выполняться весь запрос транзакции, т.е. запрос на запись, а также запросы на чтение.
Одним очень важным моментом является выполнение там запросов внутри транзакции, так как это устанавливает блокировки, и это единственный способ получить данные на реальном уровне изоляции.
Тогда все эти запросы находятся в блоке begin / commit с try / catch. В секции catch я запускаю откат и перебрасываю исключение.
Повторно выбрасывая исключение, вы можете перехватить его на более высоком уровне, то есть на том уровне, на котором вы можете решить перезапустить (цикл 3 раза) или отправить его пользователю.
В зависимости от того, как закодировано ваше приложение, есть несколько решений, чтобы справиться с этим хорошим способом:
- с использованием объектаactionManager, отвечающего за начало / принятие / отмена, все запросы в транзакции
- получить правила, например, «все транзакции обрабатываются контроллерами, ни один объект уровня DAO или DB не знает, есть ли транзакция, запущенная
- вы даже можете использовать выделенное соединение с базой данных (с правами на запись), которое используется только для TransactionManager, и сохранять исходное соединение с базой данных только для чтения для других целей.