Ответ
Пессимистическая блокировка — это стратегия управления параллельным доступом, при которой транзакция предполагает высокую вероятность конфликта и заранее блокирует данные для других транзакций.
Принцип работы:
- Транзакция A, желая изменить строку, явно запрашивает блокировку (например,
SELECT ... FOR UPDATEв SQL). - База данных немедленно блокирует эту строку для транзакции A.
- Если транзакция B попытается получить такую же блокировку на те же данные, она будет приостановлена (ждет) или получит ошибку, пока транзакция A не завершится (commit или rollback).
Реализация в JPA (Java Persistence API):
@Entity
public class Account {
@Id
private Long id;
private BigDecimal balance;
// ...
}
// В сервисном слое
@Transactional
public void transferMoney(Long fromId, Long toId, BigDecimal amount) {
// Пессимистическая блокировка записи на запись
Account fromAccount = entityManager.find(
Account.class,
fromId,
LockModeType.PESSIMISTIC_WRITE
);
// Блокировка гарантирует, что баланс не изменится другой транзакцией до commit.
if (fromAccount.getBalance().compareTo(amount) >= 0) {
fromAccount.setBalance(fromAccount.getBalance().subtract(amount));
// ... логика для получателя
}
}
| Плюсы и минусы: | Плюсы | Минусы |
|---|---|---|
| Гарантирует целостность данных, предотвращая конфликты «потерянного обновления». | Снижает производительность и масштабируемость из-за ожиданий. | |
| Проще для понимания (явная блокировка). | Высокий риск взаимных блокировок (deadlock). | |
| Подходит для операций с долгими транзакциями или высокой конкуренцией за данные. | Неэффективно, если конфликты редки. |
Альтернатива: Оптимистическая блокировка (optimistic locking), которая использует версионирование и проверяет конфликт только при коммите.
Ответ 18+ 🔞
Так, слушай, про блокировки. Есть же два лагеря: одни как будто в розовых очках — «ой, авось пронесёт, никто не тронет мои данные», а другие — законченные параноики. Вот пессимистическая блокировка — это как раз про вторых, про мудаков, которые сразу кричат «моё!» и никому не дают прикоснуться, пока сами не наиграются.
Как это работает, если на пальцах:
- Транзакция А, такая вся серьёзная, подходит к строке в базе и говорит: «Эту штуку я сейчас буду менять, и чтобы никто, блядь, даже близко не подходил». Делает
SELECT ... FOR UPDATE— это как красная лампочка загорается. - База данных тут же, как верный овчарка, хватает эту строку за горло и отдаёт под контроль транзакции А.
- Если тут же прибежит транзакция Б, такая же резвая, и попробует сделать то же самое — её просто поставят нахуй в очередь. Будет стоять, тупить, ждать, пока А всё не сделает и не отпустит замок. Либо сразу получит по ебалу с ошибкой — зависит от настроения.
Как это выглядит в коде, на JPA:
Смотри, вот у нас сущность Account, с балансом, всё как у людей.
@Entity
public class Account {
@Id
private Long id;
private BigDecimal balance;
// ...
}
// А вот в сервисе, где деньги переводят
@Transactional
public void transferMoney(Long fromId, Long toId, BigDecimal amount) {
// ВОТ ОНА, МАГИЯ ПАРАНОИКА. Не просто найти, а найти и тут же впендюрить пессимистическую блокировку на запись.
Account fromAccount = entityManager.find(
Account.class,
fromId,
LockModeType.PESSIMISTIC_WRITE
);
// Всё, теперь этот баланс — наш личный заложник. Ни одна другая транзакция его тронуть не посмеет.
if (fromAccount.getBalance().compareTo(amount) >= 0) {
fromAccount.setBalance(fromAccount.getBalance().subtract(amount));
// ... ну и там дальше логика, для получателя
}
}
Ну и что мы имеем в сухом остатке, а?
| Что хорошего (типа) | Что полное говно |
|---|---|
| Данные под бронежилетом. Никаких «ой, а я тоже только что это поменял, прости». | Производительность летит в пизду. Все стоят и ждут, как лохи. |
| Модель простая, для дебилов: взял замок — царь горы. | Взаимные блокировки (deadlock) — это твой новый кошмар. Два чувака схватили друг другу ресурсы и ждут, пока первый отпустит. Ёперный театр! |
| Идеально, если у вас там драка насмерть за одну строчку в базе, или транзакции на полчаса. | Если конфликты раз в год, то ты просто, блядь, зря всех тормозишь. Идиот. |
Короче, если ты не уверен в людях (а в своих коллег по проекту ты никогда не уверен), и знаешь, что драка будет жёсткая — можешь так делать. Но помни, за надёжность платят скоростью. А альтернатива — оптимистическая блокировка — это когда ты сначала всё делаешь, а потом при коммите смотришь: «А не ебнул ли кто-нибудь мои исходные данные пока я тут вычислял?». Если ебнул — получаешь по щам и начинаешь заново. Но зато все летают свободно, пока не столкнутся.