Этот вопрос проверяет понимание механизма оптимистичной блокировки через поле версии для предотвращения конфликтов параллельных обновлений данных.
Оптимистичная блокировка — это стратегия управления параллельным доступом к данным, которая не использует физические блокировки на уровне базы данных на время выполнения транзакции. Вместо этого она полагается на проверку версии данных в момент их сохранения.
Каждая запись в таблице содержит числовое поле (часто называемое version, revision или timestamp). При чтении данных приложение запоминает текущее значение этого поля.
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-запросами, где удерживать блокировку между запросами невозможно.
Вывод: Используйте оптимистичную блокировку через поле версии в сценариях с высокой конкурентностью на чтение и низкой вероятностью конфликтов при записи, чтобы обеспечить целостность данных без снижения производительности из-за блокировок.