>数据库将存储针对用户和货币的交易.
>每个用户每种货币都有一个余额,因此每个余额只是针对给定用户和货币的所有交易的总和.
>平衡不能是负面的.
银行应用程序将通过存储过程专门与其数据库通信.
我希望这个数据库每天接受成千上万的新交易,以及更高数量级的余额查询.为了快速提供余额,我需要预先汇总它们.与此同时,我需要保证平衡永远不会与其交易历史相矛盾.
我的选择是:
>有一个单独的余额表并执行以下操作之一:
>将交易应用于交易和余额表.在我的存储过程层中使用TRANSACTION逻辑,以确保余额和事务始终保持同步. (由Jack支持.)
>将事务应用于事务表,并具有一个触发器,用于为我更新交易金额的余额表.
>将交易应用于余额表,并有一个触发器,在交易表中为交易金额添加新条目.
我必须依赖基于安全性的方法来确保不能在存储过程之外进行任何更改.否则,例如,某个进程可以直接将事务插入到事务表中,并且在方案1.3下,相关的余额将不同步.
>拥有一个平衡索引视图,可以适当地聚合事务.存储引擎保证余额与其事务保持同步,因此我不需要依赖基于安全性的方法来保证这一点.另一方面,由于视图(甚至是索引视图)不能具有CHECK约束,因此我无法强制执行非负数的余额. (由Denny支持.)
>只有一个事务表,但有一个额外的列可以在执行该事务后立即生存余额.因此,用户和货币的最新交易记录也包含其当前余额. (建议见下文Andrew;变量由garik提出.)
当我第一次解决这个问题时,我阅读了these two讨论并决定选项2.作为参考,你可以看到它的简单实现here.
>您是否使用高负载配置文件设计或管理了这样的数据库?你对这个问题的解决方案是什么?
>你认为我做出了正确的设计选择吗?有什么我应该记住的吗?
例如,我知道对事务表的架构更改将需要重建余额视图.即使我存档事务以保持数据库较小(例如,通过将它们移动到其他地方并用摘要事务替换它们),不得不在每次模式更新时重建数千万个事务的视图,这可能意味着每次部署的停机时间明显更多.
>如果索引视图是要走的路,我怎样才能保证没有余额为负数?
存档交易:
让我详细说明存档事务和上面提到的“汇总事务”.首先,在这样的高负载系统中,定期归档是必需的.我希望保持余额和交易历史之间的一致性,同时允许将旧交易转移到其他地方.为此,我将用每个用户和货币的金额摘要替换每批存档交易.
所以,这个交易清单:
user_id currency_id amount is_summary ------------------------------------------------ 3 1 10.60 0 3 1 -55.00 0 3 1 -12.12 0
存档并替换为:
user_id currency_id amount is_summary ------------------------------------------------ 3 1 -56.52 1
通过这种方式,与归档事务的平衡可以维护完整且一致的事务历史记录.
解决方法
到目前为止,我喜欢你要去的地方,但如果这是一个实际的项目(而不是学校),那么需要将很多想法投入到业务规则中等等.一旦你有了银行系统并且在那里运行的重新设计空间不大,因为有关于人们可以获得资金的非常具体的法律.