используя блокировку Java или перехват базы данных - PullRequest
0 голосов
/ 28 февраля 2019

Каждый раз, когда поступают новые данные, я проверяю базу данных, если есть запись, связанная с новыми данными, я получаю ее и обновляю запись на основе новых данных и старой записи;если записи не существует, я создам новую запись для новых данных;

Проблема: , когда несколько потоков выполняют одно и то же, естественно, образуется шаблон read -> check -> update,в результате состояние гонки .


Я пробовал следующие решения, но оба они кажутся не совсем хорошими.

  1. Добавить уникальное ограничение в БД для aFieldOrSeveralFields, попытаться перехватить SQLIntegrityConstraintViolationException и затем повторить процесс read -> check -> update;

    • Я могу поймать Exception, но это выглядит опасно для меня;
    • или я могу проверить его по e instanceof SQLIntegrityConstraintViolationException, и пусть всплывают другие исключения, но это выглядит некрасиво ;
  2. Использование synchronised в целом read -> check -> update, но это кажется весьма неэффективным , поскольку существуют очевидные операции ввода-вывода.


Обновлено 2019-03-11

В конце, чтобы сбалансировать некрасивую обработку и эффективность , я разделил задачу на более мелкие, используя synchronised, чтобы обеспечить согласованность данных, и до сих пор не было очевидныхпроблемы с производительностью возрастают.

Ответы [ 2 ]

0 голосов
/ 01 марта 2019

На самом деле, это зависит от вашего сценария обслуживания.Если вам нужен обратный вызов немедленно, есть три способа.

Первый, пессимистическая блокировка.Этот используется в сценарии, связанном с деньгами, например, остаток на счете.

select xx from xxx.. for update
//check
//update 

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

select version, xxx,... from ... //version column is for optimistic lock
//check
update .... set ... where version = (the version you get above)

Или, может быть, вы можете попробовать управляемую событиями модель с очередью сообщений

0 голосов
/ 28 февраля 2019

Я думаю, что вы делаете правильные вещи, но что я не понимаю, почему здесь возникает исключение?(возможно, вы можете уточнить это).

Как я вижу, правильный поток выглядит следующим образом:

record <- readFromDB(uniqueFields)
if record does not exist:
    record <- createRecord()
updateFields(record) //here you should update the non-unique fields
saveToDB(record)     //it shouldn't throw an exception since the unique fields didn't change

Другое возможное решение - использование ON DUPLICATE KEY UPDATE / IGNORE на основео вашем случае использования, узнайте больше об этом здесь ,

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...