我应如何保证涉及金融交易操作的数据库的一致性

时间:2019-05-22 03:36:21

标签: node.js database mongodb algorithm backend

我试图弄清楚如何处理数据库中的一致性。 在方案中:

  • 用户A在数据库中有一个会计凭证,其中包括一个余额字段,表示其当前金额。 (假设他最初有100美元)

  • 我的系统有很多方法可以为他的帐户充值。

  • 假设同时发生两种方法,每种方法向他收取10 $的费用,这些步骤按以下顺序同时发生:
    • 方法1读取他的余额并存储在内存中(100 $)
    • 方法2读取余额并存储在内存中(100 $) ...一些业务逻辑
    • 方法1通过将内存中的变量减去10(100 $-10 $)来更新其余额,然后保存
    • 方法2通过将内存中的变量减去10(100 $-10 $)来更新其余额,然后保存

这意味着他只需要支付10美元,而不是20美元。

我搜索了这种情况一段时间,但无法弄清楚(对不起,我很愚蠢)。 非常感谢您的帮助,启发了我的头脑。 :)

2 个答案:

答案 0 :(得分:1)

您刚刚发现了金融交易为何如此复杂:-)

您是否曾经想过,为什么要花一些时间才能更新银行帐户中的余额?还是为什么您实际上有两个余额而不是一个?

那是因为您的帐户实际上可以转为负数,并且(在一定程度上)可以。

因此,在现实生活中,发生的情况是您有100美元的余额,需要支付10美元,直到收款人处理并确认该交易之前,您的余额仍为100美元。如果您进行20笔交易,每笔交易10美元,那么您将能够完成交易,因为系统很可能不会注意到。 老实说,它不应该。想想信用卡,您现在可能没有足够的钱,但是也许您知道信用到期时就会有足够的钱。

因此,您描述的竞争条件只有在您实际读取该值然后对其进行更新时才有效。

有几种方法:

  • 读取当前余额,并使用旧余额作为where语句中的字段来更新行。这样,如果它不更新任何行,您就知道您需要重新读取和更新。
  • 不更新余额,仅按时间进行,例如每小时一次。是的,您可能仍然需要进行一些检查,但是系统总体上将具有更高的响应速度。
  • 锁定数据库行是您的第一步。可以,但是有可能会使应用变慢。

答案 1 :(得分:0)

您描述的种族状况是低水平的设计问题。使用像Node这样的后端引擎将以先到先得的方式处理传入请求,您无需考虑这种情况。如果您遵守触发数据库更新回调的顺序,则描述的竞争条件是不可能的。它们的发出顺序与发出的顺序相同。因此,只有在前一个更新完成后,才应调用下一个更新。承诺是做到这一点的好方法。