Как я должен гарантировать согласованность в базе данных, связанной с операциями финансовых транзакций - PullRequest
0 голосов
/ 22 мая 2019

Я пытаюсь выяснить, как обрабатывать согласованность в базе данных.В сценарии:

  • Пользователь А имеет учетный документ в базе данных, включающий поле баланса, представляющее сумму его текущих денег.(Предполагается, что изначально у него есть 100 $)

  • В моей системе есть много методов для пополнения его счета.

  • Предположим, 2 метода происходят одновременно, каждый методвзимает с него 10 $, эти шаги выполняются одновременно в следующих порядках:
    • Метод 1 ЧИТАЙТЕ его баланс и сохраняйте в памяти (100 $)
    • Метод 2 ЧИТАЙТЕ его баланс и сохраняйте в памяти (100$) ... некоторые бизнес-логики
    • Метод 1 ОБНОВИТЕ свой баланс, вычитая переменную в памяти на 10 (100 $ - 10 $), а затем сохраняйте его
    • Метод 2 ОБНОВЛЯЙТЕ свой баланс, вычитаяпеременная в памяти на 10 (100 $ - 10 $) и затем сохранить ее

Это означает, что с него взяли только 10 $ вместо 20 $.

Я искал эту ситуацию некоторое время и не могу понять это (извините за мою глупость).Очень ценю твою помощь, чтобы просветить мой пернатый.:)

Ответы [ 2 ]

1 голос
/ 22 мая 2019

Вы только что обнаружили, почему финансовые операции сложны: -)

Задумывались ли вы, почему вам требуется время для обновления баланса на вашем банковском счете? Или почему у вас два баланса вместо одного?

Это потому, что ваша учетная запись может на самом деле стать отрицательной и (до определенного момента), что будет хорошо.

Таким образом, в сценарии реальной жизни получается, что у вас есть баланс 100 $, вы платите 10 $, и до тех пор, пока получатель не обработает и не подтвердит эту транзакцию, у вас останутся ваши 100 $. Если вы совершите 20 транзакций по 10 $ каждая, вы сможете их завершить, потому что система, скорее всего, не сможет это заметить. И, честно говоря, не должно. Подумайте о кредитных картах, у вас сейчас может не хватить денег, но, может быть, вы знаете, что у вас будет достаточно денег в срок.

Итак, условие гонки, которое вы описываете, работает, только если вы действительно прочитали значение и затем обновили его.

Есть несколько подходов:

  • Считать текущий баланс и обновить строку, используя старый баланс в качестве поля в операторе where. Таким образом, если он не обновляет строки, вы знаете, что вам нужно перечитать и обновить.
  • Не обновляйте баланс и делайте это только по времени, скажем, раз в час. Да, возможно, вам еще придется выполнить некоторые проверки, но система в целом будет более отзывчивой.
  • Заблокируйте строку базы данных в качестве первого шага. Это бы сработало, но есть вероятность, что оно замедлит работу приложения.
0 голосов
/ 22 мая 2019

Состояние гонки, которое вы описываете, является проблемой проектирования низкого уровня. С таким внутренним движком, как Node, который будет обрабатывать входящие запросы в порядке поступления заявок, вам не нужно думать об этом случае. Описанное вами состояние гонки невозможно, если вы соблюдаете порядок, в котором выполняются обратные вызовы обновления базы данных. Они запускаются в том же порядке, в котором они были выпущены. Поэтому вы должны вызывать следующее обновление только после завершения предыдущего. Обещания - отличный способ сделать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...