Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Как работает Optimistic Locking?
Optimistic Locking — это техника управления конкурентным доступом к данным, основанная на предположении, что конфликты редки. Вместо блокирования ресурса, система проверяет, изменялись ли данные, и откатывает транзакцию при обнаружении конфликта.
Основной принцип
Оптимистичная блокировка работает по принципу:
- Читаем данные без блокировки
- Выполняем бизнес-логику
- При сохранении проверяем, не изменились ли данные другим потоком
- Если изменились — откатываем и повторяем операцию
Это контрастирует с пессимистичной блокировкой, которая блокирует ресурс сразу при чтении.
Реализация через Version Number
Самый распространенный способ — использование версионирования:
@Entity
@Table(name = "users")
public class User {
@Id
private Long id;
private String name;
private String email;
@Version // Спецификация JPA для optimistic locking
private Long version;
}
Когда JPA сохраняет сущность, она генерирует SQL вроде:
UPDATE users
SET name = ?, email = ?, version = version + 1
WHERE id = ? AND version = ?
Если версия не совпадает (версия изменилась после нашего чтения) — обновление не произойдет, и будет выброшено OptimisticLockException.
Полный пример с обработкой конфликта
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional
public User updateUser(Long id, String newName) {
try {
User user = userRepository.findById(id).orElseThrow();
user.setName(newName);
// Сохранение проверит версию
return userRepository.save(user);
} catch (OptimisticLockingFailureException e) {
// Конфликт! Другой поток обновил данные
// Стратегия 1: повторить попытку
return updateUser(id, newName);
// Стратегия 2: уведомить пользователя
// throw new ConflictException("Data was modified");
}
}
}
Как это выглядит в БД
Таблица users:
id | name | email | version
1 | Alice | alice@example.com | 5
Сценарий конфликта:
Поток 1: SELECT * FROM users WHERE id=1; -- version=5
Поток 2: SELECT * FROM users WHERE id=1; -- version=5
Поток 2: UPDATE users SET name=Bob, version=6 WHERE id=1 AND version=5;
✅ Успешно! version теперь 6
Поток 1: UPDATE users SET name=Charlie, version=6 WHERE id=1 AND version=5;
❌ Ошибка! version уже 6, условие не выполнено
OptimisticLockException
Advantages и Disadvantages
Плюсы:
- Не требует блокировок — выше производительность при низкой конфликтности
- Подходит для распределенных систем
- Нет риска deadlock
- Масштабируется лучше, чем pessimistic locking
Минусы:
- Может быть неэффективно при частых конфликтах (много откатов)
- Требует retry logic в приложении
- Усложняет код
- Может привести к starvation в очень конфликтных сценариях
Когда использовать
- Используй optimistic locking для данных с редкими конфликтами (веб-приложения, CMS)
- Используй pessimistic locking для критичных операций с частыми конфликтами (финансовые системы)
Optimistic locking — мощный инструмент для масштабируемой конкурентности!