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

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

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

20 ответов

51 просмотр

Может такое быть что одновременно 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. Да, можно на настоящий апсерт переписать и протестировать. Спасибо

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

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

Господа, а что сейчас вообще с рынком труда на делфи происходит? Какова ситуация?
Rꙮman Yankꙮvsky
29
А вообще, что может смущать в самой Julia - бы сказал, что нет единого стандартного подхода по многим моментам, поэтому многое выглядит как "хаки" и произвол. Короче говоря, с...
Viktor G.
2
30500 за редактор? )
Владимир
47
а через ESC-код ?
Alexey Kulakov
29
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
14
Добрый день! Скажите пожалуйста, а какие программы вы бы рекомендовали написать для того, чтобы научиться управлять памятью? Можно написать динамический массив, можно связный ...
Филипп
7
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
Ребят в СИ можно реализовать ООП?
Николай
33
https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_h_common.erl#L174 https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_olp.erl#L76 15 лет назад...
Maksim Lapshin
20
Карта сайта