Какие основные стратегии блокировок используются при работе с базой данных?

«Какие основные стратегии блокировок используются при работе с базой данных?» — вопрос из категории Базы данных, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Блокировки обеспечивают согласованность данных в многопользовательской среде. Существует две фундаментальные стратегии.

1. Оптимистичная блокировка (Optimistic Locking)

Предпосылка: Конфликты при одновременном изменении данных редки. Проверка конфликта происходит в момент коммита транзакции. Реализация: Через поле версии или временной метки.

  • JPA/Hibernate пример:

    @Entity
    public class Account {
        @Id
        private Long id;
        private BigDecimal balance;
    
        @Version // Специальное поле для оптимистичной блокировки
        private Long version;
    }

    Механизм: При чтении объекта фиксируется его version. При обновлении в запросе UPDATE добавляется условие WHERE id=? AND version=?. Если версия изменилась (другой поток уже обновил запись), количество обновлённых строк будет 0, и JPA выбросит OptimisticLockException. Плюсы: Высокая производительность, нет долгих блокировок. Минусы: Частые конфликты приводят к большому числу откатов.

2. Пессимистичная блокировка (Pessimistic Locking)

Предпосылка: Конфликты вероятны. Данные блокируются на время транзакции. Реализация в JPA:

// Блокировка при чтении (обычно SELECT ... FOR UPDATE)
Account account = entityManager.find(
    Account.class, 
    accountId, 
    LockModeType.PESSIMISTIC_WRITE
);

// Или явная блокировка позже
entityManager.lock(account, LockModeType.PESSIMISTIC_WRITE);

Типы пессимистичных блокировок в JPA:

  • PESSIMISTIC_READ: Разделяемая блокировка (shared lock). Другие транзакции могут читать, но не изменять данные.
  • PESSIMISTIC_WRITE: Эксклюзивная блокировка (exclusive lock, FOR UPDATE). Другие транзакции не могут ни читать, ни изменять данные (зависит от СУБД).
  • PESSIMISTIC_FORCE_INCREMENT: Блокировка с одновременным увеличением поля @Version.

Плюсы: Гарантирует целостность, предотвращает конфликты. Минусы: Риск взаимоблокировок (deadlock) и снижение производительности из-за ожиданий.

Уровни блокировок в СУБД

  • Блокировка строк (Row-level lock): Блокируется только изменяемая строка. Наиболее гранулярный и предпочтительный уровень.
  • Блокировка страниц (Page-level lock): Блокируется страница данных (группа строк).
  • Блокировка таблиц (Table-level lock): Блокируется вся таблица. Сильно снижает параллелизм, используется для DDL-операций или массовых обновлений.

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