Что такое пессимистическая блокировка (Pessimistic Locking) в базах данных?

Ответ

Пессимистическая блокировка — это стратегия управления параллельным доступом, которая предполагает, что конфликты при изменении данных вероятны. Она предварительно блокирует запись (или строку) на уровне БД на время транзакции, предотвращая её изменение другими транзакциями.

Как работает: При чтении данных с намерением их обновления транзакция устанавливает блокировку (например, SELECT ... FOR UPDATE). Другие транзакции, пытающиеся получить такую же блокировку, будут ждать её освобождения или получат таймаут.

Пример в JPA (Java Persistence API):

EntityManager em = ...;
em.getTransaction().begin();
// Блокируем сущность для обновления
Product product = em.find(Product.class, productId, LockModeType.PESSIMISTIC_WRITE);
product.setStock(product.getStock() - 1); // Безопасное изменение
em.getTransaction().commit(); // Блокировка снимается

Плюсы:

  • Гарантирует целостность данных в условиях высокой конкуренции.
  • Предотвращает «потерю обновлений».

Минусы:

  • Снижает производительность и масштабируемость из-за ожиданий.
  • Повышает риск взаимных блокировок (deadlock).

Когда использовать: В системах, где данные часто конфликтуют (например, бронирование последнего билета, финансовые операции). Альтернатива – оптимистическая блокировка (с версиями), которая эффективнее при редких конфликтах.

Ответ 18+ 🔞

А, слушай, вот эта ваша пессимистическая блокировка — это как самый жадный мужик в очереди за последней бутылкой водки. Он её не просто берёт, он сразу хватает и прижимает к груди, и смотрит на всех волком: «Моё! Не трожь, пока я не отпью!». Похуй, что ты тоже хочешь — стой и жди, пока он не нажмётся или не уронит.

Как оно, блядь, работает: Ты такой приходишь в базу данных, говоришь: «Дай-ка мне запись номер пять, но так, чтобы я её сейчас обновлять собирался». База тебе её выдаёт, но сразу вешает на неё здоровенный висячий замок. Любой другой, кто попробует сказать «а мне тоже эту пятую для обновления», упрётся лбом в этот замок и будет тупить в ожидании, пока ты не закончишь свои делишки и не снимешь блокировку.

Вот, смотри, как в коде это выглядит, сука:

EntityManager em = ...;
em.getTransaction().begin();
// Берём товар и сразу кричим "ЗАНЯТО, НЕ ЛЕЗЬ!"
Product product = em.find(Product.class, productId, LockModeType.PESSIMISTIC_WRITE);
product.setStock(product.getStock() - 1); // Спокойно меняем, ибо все остальные ждут, как лохи
em.getTransaction().commit(); // Только сейчас замок щёлк — и все кидаются на освободившееся

Чем это, блядь, хорошо:

  • Данные целы, как стекло. Никакой ерунды вроде «два человека купили один и тот же последний билет». Не, тут один купил, а второй стоит и ебёт кирпич, глядя на экран «ожидайте».
  • Потерь обновлений не будет — ты первый встал, ты первый и пописал.

Чем это, ёпта, пиздецово:

  • Всё тормозит, как черепаха в сиропе. Все стоят в очередях друг за другом, производительность летит в пизду.
  • А ещё можно так красиво взаимно заблокироваться (deadlock), что все просто встанут колом. Представь: ты ждёшь, когда он отпустит пятый элемент, а он ждёт, когда ты отпустишь десятый. И оба стоите, как идиоты, до таймаута. Ёперный театр!

Когда это юзать: Ну, например, когда у тебя там битва насмерть за последний лот на аукционе или за остатки на счету. Там, где драка идёт не на жизнь, а на смерть. А если драки редкие — лучше оптимистическую брать, с версиями, это поумнее будет. Но если уже пошла мясорубка — только пессимистичная, чтоб наверняка.