Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

AI info

Карта сайта

Документы

Медиа

Назад
Вопрос про Postgres: optimistic locking, transaction, version field, concurrency control, data integrity

Как работает транзакция при использовании version-поля?

Этот вопрос проверяет понимание механизма оптимистичной блокировки через поле версии для предотвращения конфликтов параллельных обновлений данных.

Короткий ответ

Поле версии (например, `version`) — это число, которое увеличивается при каждом обновлении записи. Перед сохранением транзакция проверяет, что текущее значение версии в базе данных совпадает с тем, которое было прочитано в начале операции. Если версии не совпадают, значит, запись была изменена другим процессом, и текущая транзакция откатывается, предотвращая потерю данных. Этот подход называется оптимистичной блокировкой, так как он предполагает, что конфликты редки, и не блокирует запись на время работы транзакции.

Длинный ответ

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

Как работает механизм с version-полем

Каждая запись в таблице содержит числовое поле (часто называемое version, revision или timestamp). При чтении данных приложение запоминает текущее значение этого поля.

  • Когда приложение хочет обновить запись, оно формирует SQL-запрос UPDATE, который включает условие WHERE id = :recordId AND version = :oldVersion.
  • В этом же запросе значение поля version увеличивается (например, SET version = version + 1).
  • Если условие WHERE срабатывает (т.е. версия в базе всё ещё равна :oldVersion), запись обновляется, и количество затронутых строк равно 1.
  • Если же другая транзакция уже изменила эту запись и увеличила версию, условие WHERE не найдёт строку для обновления, и количество затронутых строк будет 0. Приложение интерпретирует это как конфликт параллельного изменения и откатывает текущую операцию, обычно выбрасывая исключение (например, OptimisticLockException).

Пример реализации

Рассмотрим простой пример на псевдокоде, моделирующий обновление баланса пользователя.

// 1. Чтение записи в начале транзакции
let user = db.query('SELECT id, balance, version FROM users WHERE id = 123');
let oldVersion = user.version;

// 2. Бизнес-логика (например, изменение баланса)
user.balance += 100;

// 3. Попытка сохранения с проверкой версии
let rowsUpdated = db.execute(
    'UPDATE users SET balance = ?, version = version + 1 WHERE id = ? AND version = ?',
    [user.balance, user.id, oldVersion]
);

if (rowsUpdated === 0) {
    // Конфликт! Другой процесс уже изменил запись.
    throw new OptimisticLockException('Запись была изменена другим пользователем.');
}
// Если rowsUpdated === 1, обновление прошло успешно.

Где применяется

Этот подход широко используется в ORM (Hibernate, Entity Framework, Django ORM), в REST API для предотвращения "lost update" и в системах, где чтение происходит значительно чаще, чем запись, и где нежелательны накладные расходы на долгие блокировки. Он типичен для веб-приложений с короткими HTTP-запросами, где удерживать блокировку между запросами невозможно.

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

Уровень

  • Рейтинг:

    4

  • Сложность:

    5

Навыки

  • Postgres

    Postgres

  • SQL

Ключевые слова

#optimistic locking

#transaction

#version field

#concurrency control

#data integrity

Подпишись на Java Developer в телеграм