Вы говорите о условиях гонки , и они чрезвычайно важны для устранения в финансовом коде.
Все, что следует шаблону получения / тестирования / установкибудет иметь огромные проблемы.Вы не можете сделать это.
Вместо этого используйте шаблон set / test / fail.Попробуйте и вычтите использование атомарного оператора SQL, такого как отдельная операция или блок транзакции.Если это приведет к отрицательному сальдо баланса, откатите его назад.
Например, это плохо :
balance = query("SELECT balance FROM accounts WHERE account_id=?")
balance -= amount
balance = query("UPDATE accounts SET balance=?")
Что-то может произойти между извлечением и записью.
Вместо этого вы можете сделать это, если этот запрос либо успешен, либо не выполнен, его нельзя прервать:
query("UPDATE accounts SET balance=balance-? WHERE account_id=? AND balance>?")
Этот запрос не будет выполнен, если не будет достаточно остатка.В результате вы получите нулевые строки, измененные.
Вы также можете сделать это с помощью бухгалтерии в стиле двойной бухгалтерской книги, попытавшись вставить необходимые строки бухгалтерской транзакции, а затем проверить SUM()
, чтобы убедиться, чтонулевой или положительный результат баланса для исходного счета.Если этого не произойдет, отмените транзакцию с ROLLBACK
.Изменения не применяются.
Существует множество способов структурировать эти операторы INSERT
, чтобы исключить отрицательное сальдо, например INSERT INTO x SELECT ... FROM y
, где вы можете применить условия к подзапросу для возврата нулевых строк.в случае недостаточного баланса.