Разница между LockModeType Jpa

я смущен работой LockModeTypes в JPA:

  1. LockModeType.Optimistic

    • он увеличивает версию во время фиксации.
    • вопрос здесь: Если у меня есть столбец версии в моей сущности, и если я не указываю этот режим блокировки, то он также работает аналогично, то в чем его польза?
  2. LockModeType.OPTIMISTIC_FORCE_INCREMENT

    • здесь он увеличивает столбец версии, хотя сущность не обновляется.
    • но какая польза от него, если какой-либо другой процесс обновил ту же строку до фиксации этой транзакции? эта транзакция в любом случае потерпит неудачу. так в чем же польза этого LockModeType.
  3. LockModeType.PESSIMISTIC_READ

    • этот режим блокировки выдает select for update nowait(если тайм-аут подсказки не указан)..
    • таким образом, в основном это означает, что никакая другая транзакция не может обновить эту строку, пока эта транзакция совершено, то его в основном блокировка записи, почему его назвали Read замок?
  4. LockModeType.PESSIMISTIC_WRITE

    • этот режим также выдает select for update nowait (если тайм-аут подсказки не указан).
    • вопрос вот в чем разница между этим режимом блокировки и LockModeType.PESSIMISTIC_READ как я вижу, оба пожара одинаковые запросы?
  5. LockModeType.PESSIMISTIC_FORCE_INCREMENT

    • это select for update nowait (если тайм-аут подсказки не указан) а также увеличивает номер версии.
    • я совершенно не понял, как это использовать.
    • почему требуется увеличение версии, если for update no wait есть?

1 ответов


я бы сначала различил оптимистические и пессимистические замки, потому что они отличаются по своему основному механизму.

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

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

теперь к списку типов замков:

  1. LockModeType.Optimistic

    • это действительно значение по умолчанию. Обычно он игнорируется, как указано ObjectDB. На мой взгляд, он существует только для того, чтобы вы могли динамически вычислять режим блокировки и передавать его дальше, даже если блокировка будет оптимистичной в конце. Не очень вероятный usecase, хотя, но это всегда хороший дизайн API, чтобы предоставить возможность ссылаться даже значение по умолчанию.
    • пример:

      LockModeType lockMode = resolveLockMode(); A a = em.find(A.class, 1, lockMode);

  2. LockModeType.OPTIMISTIC_FORCE_INCREMENT

    • это редко используемый вариант. Но это может быть разумно, если вы хотите заблокировать ссылку на этот объект другим объектом. Другими словами, вы хотите заблокировать работу с сущностью, даже если она не изменена, но другие сущности могут быть изменены в отношение к этой сущности.
    • пример: у нас есть книга и полка сущности. Можно добавить книгу на полку, но книга не имеет никакой ссылки на свою полку. Разумно заблокировать действие перемещения книги на полку, чтобы книга не оказалась на другой полке (из-за другой транзакции) до окончания этой транзакции. Чтобы заблокировать это действие, недостаточно заблокировать текущий объект книжной полки, так как книга еще не должна быть на полке. Это также не имеет смысла чтобы заблокировать все целевые книжные полки, так как они, вероятно, будут отличаться в разных транзакциях. Единственное, что имеет смысл, - это заблокировать саму книжную сущность, даже если в нашем случае она не изменяется (она не содержит ссылки на свою книжную полку).
  3. LockModeType.PESSIMISTIC_READ

    • этот режим похож на LockModeType.PESSIMISTIC_WRITE, но разные в одном: пока блокировка записи не будет установлена на том же объекте какой-либо транзакцией, она не должна блокировать чтение сущность. Он также позволяет блокировать другие транзакции с помощью LockModeType.PESSIMISTIC_READ. Различия между блокировками записи и чтения хорошо объяснены здесь (ObjectDB) и здесь (OpenJPA).
  4. LockModeType.PESSIMISTIC_WRITE

    • это более сильная версия LockModeType.PESSIMISTIC_READ. Когда WRITE блокировка на месте, JPA с помощью базы данных предотвратит любую другую транзакцию для чтения сущности, а не только для записи как с READ замок.
    • способ, как это реализуется провайдером ina JPA в сотрудничестве с базовой БД, не предписан. В вашем случае с Oracle, я бы сказал, что Oracle не дает что-то близкое к READ замок. SELECT...FOR UPDATE скорее WRITE замок. Это может быть ошибка в спящем режиме или просто решение, которое вместо реализации пользовательского "мягче"READ блокировка, тем "жестче"WRITE вместо этого используется блокировка. Это в основном не нарушает согласованность, но не содержит всех правил с READ замки. Вы можете запустить несколько простых тестов с помощью READ блокировки и длительные транзакции, чтобы узнать, могут ли другие транзакции приобретать READ блокирует тот же объект. Это должно быть возможно, тогда как не с WRITE замки.
  5. LockModeType.PESSIMISTIC_FORCE_INCREMENT

    • это еще один редко используемый режим блокировки. Тем не менее, это вариант, где вам нужно объединить PESSIMISTIC и OPTIMISTIC механизмы. С помощью равнина PESSIMISTIC_WRITE не в следующей ситуации:
      1. транзакция A использует оптимистическую блокировку и считывает сущность E
      2. транзакция B получает блокировку записи на сущности E
      3. транзакция B фиксирует и освобождает блокировку E
      4. транзакция a обновляет E и совершает
    • на шаге 4, Если столбец версии не увеличивается транзакцией B, ничто не мешает A перезаписать изменения режима B. Lock LockModeType.PESSIMISTIC_FORCE_INCREMENT заставит транзакция B для обновления номера версии и сбоя транзакции A с помощью OptimisticLockException, хотя B использовал пессимистическую блокировку.