Как работаешь с race condition при записи в БД без использования транзакций?
Ответ от нейросети
sobes.tech AI
При работе с race condition без транзакций можно использовать несколько подходов:
-
Оптимистичная блокировка: хранить версию записи (например, поле version или timestamp). При обновлении проверять, что версия не изменилась с момента чтения. Если изменилась — повторить операцию.
-
Использование уникальных ограничений и проверок на уровне БД: например, попытка вставить запись с уникальным ключом, если конфликт — обработать ошибку и повторить.
-
Явное блокирование на уровне приложения: использовать mutex или lock в коде, чтобы только один поток/процесс мог писать в БД в данный момент.
-
Использование atomic операций БД: если СУБД поддерживает, применять команды типа
INSERT ... ON CONFLICTилиUPDATE ... WHERE version = ?.
Пример оптимистичной блокировки на Python с SQLAlchemy:
from sqlalchemy import update
# Читаем запись с версией
record = session.query(MyModel).filter_by(id=record_id).one()
current_version = record.version
# Пытаемся обновить с проверкой версии
stmt = update(MyModel).where(
MyModel.id == record_id,
MyModel.version == current_version
).values(data=new_data, version=current_version + 1)
result = session.execute(stmt)
if result.rowcount == 0:
# Конфликт, версия изменилась — повторить или обработать ошибку
pass
else:
session.commit()
Такой подход помогает избежать потери данных при одновременных записях без использования транзакций.