Что такое пессимистическая блокировка (Pessimistic Locking) в Spring Data JPA?

Ответ

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

Реализация в Spring Data JPA:

  1. Использование аннотации @Lock:

    import org.springframework.data.jpa.repository.Lock;
    import javax.persistence.LockModeType;
    
    @Repository
    public interface AccountRepository extends JpaRepository<Account, Long> {
        @Lock(LockModeType.PESSIMISTIC_WRITE) // Блокировка на запись
        @Query("SELECT a FROM Account a WHERE a.id = :id")
        Account findByIdForUpdate(@Param("id") Long id);
    }
    • PESSIMISTIC_WRITE: Блокировка для обновления/удаления (обычно SELECT ... FOR UPDATE в SQL).
    • PESSIMISTIC_READ: Блокировка только для чтения, если БД поддерживает.
  2. Использование EntityManager:

    Account account = entityManager.find(Account.class, accountId, LockModeType.PESSIMISTIC_WRITE);

Как это работает в SQL (на примере PostgreSQL):

-- Spring Data JPA сгенерирует примерно такой запрос:
BEGIN;
SELECT * FROM account WHERE id = 123 FOR UPDATE; -- Строка блокируется
-- ... бизнес-логика, изменяющая account ...
UPDATE account SET balance = 1000 WHERE id = 123;
COMMIT; -- Блокировка снимается
Плюсы и минусы: Плюсы Минусы
Гарантирует целостность данных в высококонкурентных сценариях. Высокий риск взаимных блокировок (deadlocks).
Простая концепция. Снижает пропускную способность (производительность).
Требует коротких транзакций.

Область применения: Финансовые операции (списание/зачисление), бронирование, управление инвентарём — где строгая согласованность критична.

Ответ 18+ 🔞

А, пессимистическая блокировка! Ну это ж классика, блядь, как Герасим с Муму — либо всё, либо нихуя!

Смотри, суть проще пареной репы, но с подвохом. Это когда ты такой недоверчивый параноик в базе данных. Ты читаешь запись и сразу, блядь, хватаешь её в ежовые рукавицы, навешиваешь замок и не отпускаешь, пока свои дела не сделаешь. «Моё! Не трогай, пока я не закончил!» — вот твой девиз. Другие транзакции будут тупить в очереди, как лохи, ждать, пока ты свой геморрой завершишь.

Как это в Spring JPA приколоть:

Первый способ — через репозиторий, по-пацански, с аннотацией. Смотри, какой красавчик-код:

import org.springframework.data.jpa.repository.Lock;
import javax.persistence.LockModeType;

@Repository
public interface AccountRepository extends JpaRepository<Account, Long> {
    @Lock(LockModeType.PESSIMISTIC_WRITE) // Всё, приехали. Блокировка на запись, жёсткая.
    @Query("SELECT a FROM Account a WHERE a.id = :id")
    Account findByIdForUpdate(@Param("id") Long id);
}

PESSIMISTIC_WRITE — это и есть наш «SELECT ... FOR UPDATE», классика жанра. Будет блокировать, пока не отпустишь. Есть ещё PESSIMISTIC_READ, но это для особых извращенцев, не все базы это любят.

А можно и через EntityManager, по-стариковски, напрямую:

Account account = entityManager.find(Account.class, accountId, LockModeType.PESSIMISTIC_WRITE);

Всё, чувак, объект account теперь под колпаком. Никто его тронуть не может.

А на самом деле, в недрах базы, происходит вот такая магия (PostgreSQL для примера):

BEGIN;
SELECT * FROM account WHERE id = 123 FOR UPDATE; -- Всё, строка в оковах, блядь!
-- ... тут ты цацкаешься с данными, меняешь баланс, ебёшь мозги...
UPDATE account SET balance = 1000 WHERE id = 123;
COMMIT; -- Ура! Отпустил на волю. Следующий, подходи!

Ну и теперь, как всегда, ложка дёгтя в бочку мёда. Плюсы и минусы:

Что хорошего (Плюсы) Что за пиздец (Минусы)
Данные под защитой, как в танке. Никаких конфликтов при одновременном доступе. Взаимные блокировки (deadlocks) — это твоя новая реальность. Два потока заблокировали друг другу ресурсы и сидят, ссут друг на друга. Ёперный театр!
Концепция — проще некуда. Прочитал — залочил — работай. Производительность летит в тартарары. Все стоят, ждут, когда ты, мудак, разблокируешь запись. Пропускная способность — ноль ебать.
Транзакции должны быть короткими, как крик «Муму!». Иначе всех заморозишь.

Где это воткнуть? Да там, где по-другому — пиздец. Финансы: списание бабла, переводы. Бронирование билетов или мест в отеле. Управление остатками на складе, где последняя единица товара. Короче, везде, где ошибка стоит дороже, чем тормоза.

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