Куда БЛОКИРОВАТЬ, чтобы получить атомарный get-or-create объекта-строки - PullRequest
0 голосов
/ 25 января 2019

Я хочу иметь метод getOrCreateFoobar(id), который либо получает уже существующий Foobar на id, либо создает / вставляет новый Foobar с id.Этот метод будет вызываться с высокой степенью одновременности, поэтому я должен сериализовать / синхронизировать доступ для этого атомарного метода get-or-create, чтобы не два одновременных запроса дважды создавали Foobar с одним и тем же идентификатором.

ПосколькуСущность может еще не существовать, пока нет ни одной строки, по которой я мог бы заблокировать синхронизацию.кроме того, блокировка всей таблицы также кажется плохой идеей - потенциальный рецепт тупиковой катастрофы (?)

Существует такой шаблон для создания искусственных объектов, таких как LockEntity, которые могут иметь свойство типа Name.Для каждого UseCase я предоставляю строку / экземпляр типа Name=GET_OR_CREATE_FOOBAR.Который затем используется в репозитории с замком PESSIMISTIC_WRITE:

    @Lock(LockModeType.PESSIMISTIC_WRITE)
    @Query("SELECT e FROM LockEntity e WHERE name = :name")
    LockEntity obtainLock(@Param("name") String name);

, который затем можно использовать как:

    obtainLock("GET_OR_CREATE_FOOBAR")
    // now we hold the lock and are synchronized
    get()
    if (doesNotExistYet) create()
    commit / release-lock

Есть ли лучший / более легкий способ?

1 Ответ

0 голосов
/ 25 января 2019

Поскольку параметр равен id, и поскольку вы ожидаете только одно значение назад, можно с уверенностью предположить, что id уникально, поэтому создайте UNIQUE INDEX для столбца (если это не так, например,Первичный ключ), и будет невозможно для двух одновременных запросов создать Foobar с одним и тем же идентификатором дважды.

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

loop:
   get()
   if found:
      return it
   insert()
   if ok:
      return it
   if failure is not duplicate value error:
      fail
   short wait
end loop
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...