【问题标题】:SQL SUM expression and LockSQL SUM 表达式和锁
【发布时间】:2017-03-21 00:40:33
【问题描述】:

我对正确的 SQL 解决方案有疑问。

现状: 我的数据库包含银行交易表(信用卡和借记卡)。

  • 信用交易被签署为正数 (+),并且
  • 借记交易为负金额 (-)。

使用数据库的应用程序是一个多用户 webapp,因此事务表包含许多行,这些行引用不同的用户。 一些 webapp 操作需要检查登录用户的实际余额,使用 Transactions 表并保存借记 Transaction(操作价格)。

我在思考这个机制的架构,有一些疑问:

  1. 每次用户请求时将余额计算为交易贷方和借方的总和是否是个好主意?我知道这对 db 可能效率低下。也许我应该在某处保存快照?

  2. 当一个用户检查“余额”作为贷记/借记交易的总和,而另一个用户同时保存借记交易(因为他/她更快)时,如何确保数据内聚?我想到了一个悲观的锁,但我应该锁什么?我知道在 Postgresql(我使用的数据库)上可能无法使用聚合锁 (SUM)。”

对不起我的英语,我希望我的问题是可以理解的。 :)

【问题讨论】:

    标签: sql database postgresql database-concurrency


    【解决方案1】:

    如果您想避免在用户帐户上出现余额,这可能会有更好的性能,我会尝试的方法是:

    • 每笔交易仅与一个帐户相关。
    • 每笔交易都会有该交易后的账户余额。

    因此,该帐户的最后一笔交易将具有当前余额。

    例如:

    TransactionId | AccountId | Datetime | Ammount | Balance 
                1 |         1 | 7/11/16  |       0 |       0 
                2 |         1 | 7/11/16  |     500 |     500 
                3 |         1 | 7/11/16  |     -20 |     480 
                4 |         1 | 8/11/16  |      50 |     530 
                5 |         1 | 8/11/16  |    -200 |     330 
    

    通过这种方式,您将能够获取帐户余额(使用该 accountId 的最后一笔交易),并且您将能够更好地了解余额随时间的变化。

    【讨论】:

    • 谢谢。那么按日期时间对交易进行排序(对于给定的 AccountId),然后获取最后一笔交易,然后在执行时锁定它:检查余额并保存另一笔交易是一个好主意吗?我的 TransactionId 主键是一个 UUID,所以我不能按它排序。日期时间精度怎么样?例如。当一些事务具有相同的 dateTime (DD/MM/YYYY HH:mm:ss.SSS) 时的情况 - 有可能吗?
    • @user6492999 1) 您应该锁定它。当您插入一笔新交易时,您要确保您选择最后一笔交易的余额。如果您预计流量会很高,请务必阅读有关数据库事务的信息,以优化操作并避免死锁。
    • @user6492999 2) 我认为精度非常高,但即使我会测试两个连续插入是否有可能具有相同的日期时间,这可能会导致不一致。日期时间精度可以在数据库引擎文档中找到。对于 Postgresql,您可以在此处找到最新版本 (9.6):postgresql.org/docs/9.6/static/datatype-datetime.html
    【解决方案2】:

    我会考虑:

    在帐户记录中存储余额以及余额准确的日期。

    获取当前余额是读取帐户余额,然后包括自该日期以来的所有交易。

    您可以有一个计划作业,该作业在午夜后一小时重新计算和时间戳。

    或者(这是我的首选解决方案):

    每次加载一笔交易或一批交易时,锁定相关账户记录并使用插入中的值更新它们作为同一交易的一部分。

    这具有序列化对帐户的访问的优势,然后可以帮助确定交易是否可以继续,因为基于余额计算的决定。

    【讨论】:

      猜你喜欢
      • 2019-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-11
      相关资源
      最近更新 更多