Я знаю, что это старый вопрос, но некоторые из нас все еще бьют по нему и смотрят на небо, блуждая как. Вот одна проблема, с которой я столкнулся,
У нас есть менеджер очередей, который опрашивает данные и передает их обработчикам для обработки. Чтобы избежать повторного получения тех же событий, менеджер очередей блокирует запись в базе данных с состоянием LOCKED.
void poll() {
record = dao.getLockedEntity();
queue(record);
}
этот метод не был транзакционным, но dao.getLockedEntity()
был транзакционным с 'REQUIRED'.
Все хорошо и в дороге, после нескольких месяцев производства, он вышел из строя с исключением оптимистической блокировки,
После большого количества отладок и проверки деталей мы можем обнаружить, что кто-то изменил код, подобный этому,
@Transactional(propagation=Propagation.REQUIRED, readOnly=false)
void poll() {
record = dao.getLockedEntity();
queue(record);
}
Таким образом, запись была поставлена в очередь еще до того, как транзакция в dao.getLockedEntity () была зафиксирована (она использует ту же самую транзакцию метода poll), и объект был изменен обработчиками (различными потоками) к моменту poll () транзакция метода получена.
Мы исправили проблему, и теперь она выглядит хорошо.
Я думал о том, чтобы поделиться им, потому что исключение из-за оптимистической блокировки может сбить с толку и его трудно отладить. Кто-то может получить пользу от моего опыта.
С уважением
Lyju