← Назад к вопросам

Как работает Optimistic Locking?

2.3 Middle🔥 171 комментариев
#Базы данных и SQL

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как работает Optimistic Locking?

Optimistic Locking — это техника управления конкурентным доступом к данным, основанная на предположении, что конфликты редки. Вместо блокирования ресурса, система проверяет, изменялись ли данные, и откатывает транзакцию при обнаружении конфликта.

Основной принцип

Оптимистичная блокировка работает по принципу:

  1. Читаем данные без блокировки
  2. Выполняем бизнес-логику
  3. При сохранении проверяем, не изменились ли данные другим потоком
  4. Если изменились — откатываем и повторяем операцию

Это контрастирует с пессимистичной блокировкой, которая блокирует ресурс сразу при чтении.

Реализация через 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 — мощный инструмент для масштабируемой конкурентности!

Как работает Optimistic Locking? | PrepBro