Ответ
Оптимистичная блокировка (Optimistic Locking) — это стратегия управления конкурентным доступом к данным, основанная на предположении, что конфликты между транзакциями происходят редко. Вместо физической блокировки записей на время транзакции используется механизм проверки версии данных при их обновлении.
Принцип работы:
- Транзакция читает данные вместе с их версией (например, числовым полем
versionили меткой времени). - Производятся изменения в памяти.
- При попытке сохранения (
UPDATE) в запрос добавляется условиеWHERE version = [прочитанное_значение]. - Если за это время данные не изменились (версия совпадает), обновление проходит успешно, и версия инкрементируется.
- Если другая транзакция уже обновила данные (версия изменилась), условие
WHEREне срабатывает, и текущая транзакция завершается с ошибкой (например,OptimisticLockException).
Реализация в JPA/Hibernate с аннотацией @Version:
@Entity
public class Account {
@Id
private Long id;
private BigDecimal balance;
@Version // Поле автоматически управляется фреймворком
private Long version;
}
| Плюсы и минусы: | Плюсы | Минусы |
|---|---|---|
| Высокая производительность (отсутствуют блокировки, препятствующие чтению). | Требует обработки конфликтов (повторные попытки или уведомление пользователя). | |
| Масштабируемость. | Не подходит для сценариев с очень высокой конкуренцией за одни и те же данные. | |
| Избегает взаимных блокировок (deadlocks). |
Ответ 18+ 🔞
А, оптимистичная блокировка, говоришь? Ну это как в жизни, блядь. Представь: ты пришёл в магазин, последний пирожок с вишней на полке лежит. Ты его видишь, запоминаешь, что он там, и идёшь за деньгами в машину. А пока ты шёл, какой-то хитрожопый ушлёпок уже этот пирожок схватил и сожрал. Ты возвращаешься, а там пусто. Вот тебе и весь принцип, в рот меня чих-пых!
То есть, сука, ты не стоишь над пирожком с битой, охраняя его, как маньяк (это пессимистичная блокировка, ебать её в сраку). Ты просто надеешься, что за время твоего отсутствия никто не сожрёт твой десерт. Но если сожрали — ну, сорян, иди нахуй, конфликт, получай исключение в ебало и решай, что делать.
Как это технически выглядит, ёпта:
- Ты читаешь запись из базы. Допустим,
account.balance = 1000иaccount.version = 5. Запоминаешь эту пятёрку, как святую. - Ты там у себя в коде эту тысячу меняешь, допустим, отнимаешь сто.
- И вот, сука, ключевой момент! Когда идёшь сохранять, пишешь в базу не просто
UPDATE account SET balance = 900 WHERE id = 1, аUPDATE account SET balance = 900, version = 6 WHERE id = 1 AND version = 5. - Если за это время никто не трогал запись, версия совпадёт, обновление пройдёт, и версия станет 6. Всё, пирожок твой.
- А если пока ты считал, какой-то пидарас шерстяной уже успел снять деньги и обновил версию до 6, твоё условие
WHERE version = 5нихуя не найдёт, и строки не обновится. Твоя транзакция, понимаешь, накрывается медным тазом с крикомOptimisticLockException. Иди, чувак, теперь думай: то ли пользователю сказать «извини, обнови страницу», то ли заново логику выполнить.
В коде на JPA это вообще красота, один аннотацией делается:
@Entity
public class Account {
@Id
private Long id;
private BigDecimal balance;
@Version // Вот эта волшебная палочка, блядь! Фреймворк сам всё сделает.
private Long version;
}
Хибернейт сам будет за тебя инкрементить эту версию при каждом апдейте и проверять её в WHERE. Удобно, блядь, как швейцарские часы.
А теперь плюсы и минусы, как есть:
| Что хорошо, ёбта? | Что плохо, нахуй? |
|---|---|
| Скорость, блядь! Никаких физических блокировок, которые всё тормозят. Читать могут все, когда угодно. | Конфликты надо обрабатывать. Не получилось с первого раза — пиши логику повтора или выводи пользователю «ой, данные устарели, обнови». |
| Масштабируется овердохуища. Тысячи потоков могут читать данные без проблем. | Для драк не годится. Если у тебя десять потоков бьются за обновление одной и той же строчки каждую секунду, то это будет пиздец, а не оптимизм. Сплошные исключения и повторные попытки. |
| Мёртвых хваток (deadlock) не бывает. Потому что никто никого не ждёт и не блокирует. |
В общем, стратегия для вежливых людей, которые не часто дерутся за один пирожок. А если дерутся — тогда уже пессимистичная блокировка, или вообще перепроектировать логику, чтобы не было такой ебли.