middle
Оптимистичная и пессимистичная блокировки
Блокировки решают проблему потерянных обновлений (lost updates), когда два потока одновременно читают и обновляют одну и ту же запись.
Оптимистичная блокировка (@Version)
Предполагает, что конфликты редки. Проверяет версию записи при обновлении. Если версия изменилась — бросает исключение.
Пример
@Entity
public class Product {
@Id
private Long id;
private String name;
private BigDecimal price;
@Version // Hibernate автоматически управляет этим полем
private Long version;
}
Сгенерированный SQL:
Пример
-- При UPDATE Hibernate проверяет version:
UPDATE products SET name = ?, price = ?, version = 2
WHERE id = 1 AND version = 1;
-- Если version изменилась → 0 строк обновлено → OptimisticLockException
Пессимистичная блокировка (LockModeType)
Блокирует строку в БД (SELECT … FOR UPDATE), предотвращая конкурентный доступ.
Пример
// JPA
Product product = entityManager.find(Product.class, id,
LockModeType.PESSIMISTIC_WRITE);
// SQL: SELECT * FROM products WHERE id = 1 FOR UPDATE
// Spring Data JPA
@Lock(LockModeType.PESSIMISTIC_WRITE)
@Query("SELECT p FROM Product p WHERE p.id = :id")
Optional<Product> findByIdForUpdate(@Param("id") Long id);
Типы LockModeType
| Тип | SQL | Назначение |
|---|---|---|
| PESSIMISTIC_READ | FOR SHARE | Разрешает concurrent reads, блокирует writes |
| PESSIMISTIC_WRITE | FOR UPDATE | Блокирует и reads, и writes |
| PESSIMISTIC_FORCE_INCREMENT | FOR UPDATE + version++ | Для update с инкрементом версии |
Сравнение
| Критерий | Оптимистичная | Пессимистичная |
|---|---|---|
| Механизм | Проверка версии при UPDATE | Блокировка строки в БД |
| Конфликт | Обнаружение (exception) | Предотвращение (ожидание) |
| Производительность | Выше при редких конфликтах | Выше при частых конфликтах |
| Deadlock | Нет | Возможен |
Важное
- Оптимистичная —
@Version, проверка при UPDATE, исключение при конфликте; подходит для большинства сценариев - Пессимистичная — FOR UPDATE, блокировка строки; для критичных операций (списание средств, резервирование)
@Versionможет быть Long, Integer, Timestamp (Long предпочтительнее)- Оптимистичная блокировка работает и между HTTP-запросами (stateless)
Частые ошибки
- Не использовать блокировки вообще — lost updates в конкурентном приложении неизбежны
- Пессимистичная блокировка без таймаута — бесконечное ожидание при deadlock; задайте
javax.persistence.lock.timeout @Versionна поле, которое обновляется вручную — Hibernate должен управлять version автоматически- Оптимистичная блокировка для частых конфликтов — постоянные OptimisticLockException ухудшают UX; используйте пессимистичную
Как используется в 2026
- Оптимистичная блокировка (
@Version) — стандарт по умолчанию для большинства сущностей - Пессимистичная — для финансовых операций, инвентаря, резервирования
- Для распределённых систем — distributed locks (Redis, Zookeeper) вместо БД-блокировок
На собеседовании: начните с проблемы lost updates, затем покажите два решения. Оптимистичная —
@Version, подходит в 90% случаев. Пессимистичная — FOR UPDATE, для финансов и критичных операций. Интервьюер может спросить про deadlock при пессимистичной блокировке — упомяните таймаут.