Указан код SQLAlchemy в следующем шаблоне:
def update_quantity(id, quantity):
try:
created = MyTable(id=id, quantity=quantity)
session.add(created)
session.commit()
except sqlalchemy.exc.IntegrityError:
session.rollback()
try:
record = MyTable.query.filter(MyTable.id=id).one()
record.quantity = record.quantity + quantity
session.commit()
except sqlalchemy.orm.exc.NoResultFound:
session.rollback()
update_quantity(id, quantity)
finally:
session.close()
, где база данных - MySQL, autocommit = False
, а уровень изоляции установлен на REPEATABLE READ
.
С в отношении предотвращения обновления количества двумя параллельными процессами несогласованным образом (например, один с устаревшим значением количества),
- Не является повторяемым Чтение, достаточное для предотвращения такого рода аномалии обновления (т.е. он уже не прошел одну из попыток обновления?)
- Если это так, есть ли причина использовать (или избегать использования) FOR UPDATE в запросе записи, т.е.
record = MyTable.query.filter(MyTable.id=id).for_update().one()
? Не будет ли принудительно откат другого обновления в любом случае? - Я специально использовал
record.quantity = record.quantity + quantity
, чтобы вызвать проблему с устаревшим обновлением; но если бы я сделал вместо этого record.quantity = MyTable.quantity + quantity
- что, я думаю, переводится как UPDATE my_table SET quantity = quantity + %d WHERE id = %d
и должно быть atomi c - можно ли вообще избежать всего состояния гонки?