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

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

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

20 ответов

47 просмотров

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

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

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

30500 за редактор? )
Владимир
47
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
вы делали что-то подобное и как? может есть либы готовые? увидел картинку нокода, где всё линиями соединено и стало интересно попробовать то же в ddl на lua сделать. решил с ч...
Victor
8
Подскажите пожалуйста, как в CustomDrawCell(Sender: TcxCustomGridTableView; ACanvas: TcxCanvas; AViewInfo: TcxGridTableDataCellViewInfo; var ADone: Boolean); получить наз...
A Z
7
Ребят в СИ можно реализовать ООП?
Николай
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
Как передать управляющий символ в открытую через CreateProcess консоль? Собсна, есть процедура: procedure TRedirectThread.WriteData(Data: OEMString); var Written: Cardinal;...
Serjone
1
Он в одиночку это дело запилил или была какая-то команда?
Aquinary
12
~ 2m21s  nix shell github:nixos/nixpkgs#stack ~  stack ghc -- --version error: … while calling the 'derivationStrict' builtin at /builtin/derivation.nix:...
Rebuild your mind.
6
Всем привет, нужна как никогда, нужна помощь с IO в загрузчике. Пишу в code16 после установки сегментных регистров, пишу вывод символа. Пробовал 2 варианта: # 1 mov $0x0E, %a...
Shadow Akira
14
Карта сайта