Как Hibernate делает проверку версии строки на Оптимистическую блокировку перед совершением транзакции - PullRequest
0 голосов
/ 25 октября 2018

Когда перед фиксацией текущей транзакции hibernate проверяет версию строки, он должен выполнить оператор sql select для извлечения строки.

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

Мне интересно, как hibernate может быть уверен, что во временном интервале между выбором строки и совершением текущей транзакции никакая другая транзакция не обновит строку, изменяя ее номер версии?Единственная возможная вещь, которую может сделать hibernate, - это выбор версии строки с пессимистической блокировкой с использованием Select ... For Update или транзакция с таким уровнем изоляции, который заблокирует читаемую строку.

Если яМысль верна:

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

  • в противном случае у нас есть короткий промежуток времени между проверкой версии строки и коммитом, где может возникнуть условие гонки.

Пожалуйста, поделитесь своими мыслями.

1 Ответ

0 голосов
/ 28 октября 2018

Для механизма оптимистической блокировки по умолчанию, указанного в аннотации @Version, такой риск отсутствует.

Как объясняется в этой статье , оптимистическая блокировка не требует никакойдополнительный SELECT для получения и проверки версии после изменения объекта.Итак, существует два шага:

  1. Объект извлекается из БД вместе с его версией:

    SELECT * FROM PRODUCT WHERE ID = 1;
    
  2. ОБНОВЛЕНИЕ илиDELETE будет использовать версию, выбранную тем же SELECT, который выбрал сущность:

    UPDATE PRODUCT SET (LIKES, QUANTITY, VERSION) = (5, 10, 3) 
    WHERE ID = 1 AND VERSION = 2;
    

Таким образом, Hibernate не проверяет версию сущности.БД проверяет это с помощью предложения WHERE.Hibernate проверяет только результат updateCount вызова метода PreparedStatement.executeUpdate.Если счетчик не равен updateCount, это означает, что либо строка была удалена, либо версия имеет изменения, а это означает, что мы используем устаревшие данные, поэтому будет выдано OptimisticLockException.

Следовательно, для оптимистической блокировки на основе @Version не может возникнуть конфликтов, поскольку запись может быть изменена только одной транзакцией за раз, и как только строка заблокирована модификацией, блокировка будетсохраняется до тех пор, пока транзакция не завершится или не откатится.

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

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