169 похожих чатов

Подскажите с кейсом, плз. Клиент шлет 2 одновременных запроса, которые создают

какую-то запись в базе с уникальным ключом. У меня код весь на апсерт, т.е. сначала проверяет, есть ли такая запись в базе, и либо модифицирует, либо вставляет. И все это обернуто в трай-кетч-DataIntegrityViolationException как раз на случай с двумя параллельными запросами. И все работает нормально со стороны клиента, запросы идемпотенты, возвращается 2 одинаковых ответа.
Но мне не нравится, что хибер и jdbc пишут в лог-еррор, что транзакция упала. С точки зрения бизнес-кода, это вполне валидное поведение, там рассчитано на то, что транзация упадет.
Можно как-то в спринге указать, что конкретно эта транзакция может упасть и не надо срать мне в логи?

20 ответов

12 просмотров

Может такое быть что одновременно 2 тредки поймут что нет записи и создадут эти 2 одинаковые записи?

Stanislav-Markin Автор вопроса
Maxim
Может такое быть что одновременно 2 тредки поймут ...

Такое постоянно и происходит. Тогда одна из транзакций упадет на DataIntegrityViolationException и опять перезапустится. В новой транзакции уже будет видна новая запись от другой транзации и запись просто будет обновлена

Stanislav Markin
Такое постоянно и происходит. Тогда одна из транза...

Можно сделать синхронизацию тредок, синхронизировать на каком-то id поле. И тогда не будут таких ошибок

Stanislav-Markin Автор вопроса
Maxim
Можно сделать синхронизацию тредок, синхронизирова...

В теории можно, но на практике запросы могут попасть на разные инстансы. Можно было бы конечно какой-то распределенный лок, но нафига? Оно все нормально отрабатывает, падающие транзакции — вполне валидный бизнес кейс

Stanislav Markin
Такое постоянно и происходит. Тогда одна из транза...

Написать аспект, который будет кетчить твой ексепшн?

Stanislav-Markin Автор вопроса

А как это спасет? Может я не очень понимаю в аспектах, но моя проблема в том, что у меня лог.ерроры от хибера прилетают. Я только от этих лишних логов хочу избавиться

а что за бд используется? insert on duplicate key update не вариант прикрутить?

Stanislav-Markin Автор вопроса
Stanislav Markin
ага, и еще внутри jdbc

Эммм. А какой класс логгирует? Потому что сколько помню кидается исключение и ничего не логгируется

Stanislav Markin
ага, и еще внутри jdbc

Ты же их перехватываешь и обрабатываешь?) Дальше прокидываешь?

Если логи действительно мешают (алерты на основе них, например), то в целом можно отключить логгер на уровне того класса и добавить свою логирующую обертку

Stanislav-Markin Автор вопроса
Alexandr ∨∧‾ Emelyanov
Эммм. А какой класс логгирует? Потому что сколько ...

В этих двух org.hibernate.engine.jdbc.batch.internal.BatchingBatch org.hibernate.engine.jdbc.spi.SqlExceptionHelper

Stanislav-Markin Автор вопроса
Alexandr ∨∧‾ Emelyanov
Ты же их перехватываешь и обрабатываешь?) Дальше п...

я на уровне сервиса ловлю DataIntegrityViolationException, не логирую и перезапускаю транзакцию

Stanislav-Markin Автор вопроса
Alexandr ∨∧‾ Emelyanov
А ты их сам включал?

у меня на org.* стоит уровень WARN

Stanislav Markin
у меня на org.* стоит уровень WARN

Я просто ни разу не видел что бы они что то логгировали

Alexandr ∨∧‾ Emelyanov
Я просто ни разу не видел что бы они что то логгир...

Сами живем с такой штукой, правда не сильно на неё ругаемся Выжимка из SqlExceptionHelper::logExceptions if (!previousErrorMessages.contains(sqlException.getMessage())) { LOG.error(sqlException.getMessage()); previousErrorMessages.add(sqlException.getMessage()); } Выше хорошо предложили, как по мне: отключить лог и залогировать самому в нужных местах

DataIntegrityViolation это не про конкурентный доступ, а про ограничения домена. Если эта ошибка возникает у тебя при конкурентном доступе значит неправильно написан запрос апсерта (он должен изменить, вставить или ничего не делать, но не бросать это исключение при конкурентном доступе). При правильной конфигурации база умеет разруливать одновременный доступ к одним и тем же данным.

Stanislav-Markin Автор вопроса
akalexus
DataIntegrityViolation это не про конкурентный дос...

у меня там не совсем настоящий апсерт, а апсерт для бедных — сначала делается repo.find, и если он ничего не вернул, то делает repo.insert. Да, можно на настоящий апсерт переписать и протестировать. Спасибо

Похожие вопросы

Обсуждают сегодня

@MrMiscipitlick А можешь макрос написать, который будет вычислять смещение относительно переданных меток? Просто .label1-.label2, и вернуть значение.
КТ315
35
я не магистр хаскеля, но разве не может лейзи тип конвертнуться в не-лейзи запросив вычисление содержимого прям при инициализации?
deadgnom32 λ madao
100
А еще в перле можно уже @arr1 + @arr2?
Sergei Zhmylove
53
Подобного рода ;Следующие три строки это директивы ассемблера, ;которые можно не задавать, т.к.работаем в Visual Studio. ;Символ ";" - это начало однострочного комментария ...
Егор Анелькин
3
Привет всем. появился вопрос. Разрабатываю сайт, в данный момент он запущен. Хостинг beget. Добавляю на сайт яндекс метрику с помощью полей client-settings (взято отсюда http...
Andrew
2
Кто-нибудь знает почему SPM клонирует репо целиком? Некоторые репы просто огромные, как та же swift-syntax которая нужна для использования макросов. Сначала подумал, что это...
iMike
6
Подскажите, где смотреть результат выполнения программы? Код: ;.686 ;Система команд процессора 686 ;.MODEL FLAT,stdcall ;Модель памяти плоская, станда...
Егор Анелькин
5
Привет. Я верно понимаю, что в определении класса Монад m — зафиксирован (к тому же поскольку это моноид в категории эндофункторов). Т.е. используя байнд я не могу перемещать...
Arseny
5
еще вопрос, допустим мы создадим char массив из 10 элементов и присвоим ему через сканф 10 символов. и выведем все символы. Хотел спросить последний элемент /0 будет включать...
Anthem
11
;.686 ;Система команд процессора 686 ;.MODEL FLAT,stdcall ;Модель памяти плоская, стандартный ;вызов процедуры ;option casemap:no...
Егор Анелькин
1
Карта сайта