我正在为一个简单的银行数据库编写架构。以下是基本规格:
银行应用程序将专门通过存储过程与其数据库通信。
我希望这个数据库每天接受数十万个新事务,以及更高数量级的平衡查询。为了非常快速地提供余额,我需要预先汇总它们。同时,我需要保证余额永远不会与其交易历史相矛盾。
我的选择是:
有一个单独的balances
表并执行以下操作之一:
将事务应用于transactions
和balances
表。TRANSACTION
在我的存储过程层使用逻辑来确保余额和交易始终同步。(由杰克支持。)
将交易应用到transactions
表并有一个触发器,balances
用交易金额为我更新表。
将交易应用到balances
表中,并有一个触发器transactions
为我在表中添加一个新条目,其中包含交易金额。
我必须依靠基于安全的方法来确保在存储过程之外不能进行任何更改。否则,例如,某些进程可以直接将事务插入transactions
表中,并且在该方案1.3
下相关余额将不同步。
有一个balances
索引视图,可以适当地聚合事务。存储引擎保证余额与其交易保持同步,因此我不需要依赖基于安全的方法来保证这一点。另一方面,我不能再强制余额为非负数,因为视图——甚至索引视图——不能有CHECK
约束。(由丹尼支持。)
只有一个transactions
表,但有一个额外的列来存储该交易执行后立即生效的余额。因此,用户和货币的最新交易记录也包含其当前余额。(下面由Andrew建议;由garik提出的变体。)
当我第一次解决这个问题时,我阅读了这 两个讨论并决定了 option 2
。作为参考,您可以在此处查看它的基本实现。
您是否设计或管理过这样的具有高负载配置文件的数据库?你对这个问题的解决方案是什么?
你认为我做出了正确的设计选择吗?有什么我应该记住的吗?
例如,我知道对transactions
表的架构更改需要我重建balances
视图。即使我正在归档事务以保持数据库较小(例如,将它们移到其他地方并用摘要事务替换它们),每次架构更新时都必须重建数千万个事务的视图,这可能意味着每次部署的停机时间会显着增加。
如果索引视图是要走的路,我如何保证没有余额为负?
归档交易:
让我详细说明一下存档交易和我上面提到的“摘要交易”。首先,在像这样的高负载系统中,定期存档将是必要的。我想保持余额与其交易历史之间的一致性,同时允许将旧交易转移到其他地方。为此,我将用每个用户和货币的金额摘要替换每批存档交易。
因此,例如,此交易列表:
user_id currency_id amount is_summary
------------------------------------------------
3 1 10.60 …
Run Code Online (Sandbox Code Playgroud) sql-server-2008 database-design sql-server aggregate materialized-view
我正在创建会计软件。我需要强制执行复式簿记。我有一个经典的问题,每笔交易一行而不是两行。
让我们举一个例子,看看它是如何在这两种情况下实现的。
考虑 accountCash
和 account Rent
。当我支付每月租金时,我会从我的Cash
帐户中将 100 美元转入我的Rent
帐户。
在一行系统中,此类事务将存储为:
交易
tx_id | posting_date
1 | 23/05/2015
Run Code Online (Sandbox Code Playgroud)
交易记录
id | tx_id | credit_account | debit_account | amount
1 | 1 | Cash | Rent | 100.00
Run Code Online (Sandbox Code Playgroud)
在两行系统中,我必须镜像相同的交易记录以创建相反的记录,一旦我将两者相加,我就会得到零余额。
交易
tx_id | posting_date
1 | 23/05/2015
Run Code Online (Sandbox Code Playgroud)
交易记录
id | tx_id | type | account | amount
1 | 1 | credit | Cash | 100.00
2 | 1 | debit | Rent | 100.00 …
Run Code Online (Sandbox Code Playgroud)