【问题标题】:Table structure for financial transactions in Mysql?Mysql中金融交易的表结构?
【发布时间】:2020-04-20 00:00:59
【问题描述】:

我正在开发一个可以进行金融交易的系统。在这个系统中,用户可以插入或取款、买卖产品、向其他用户汇款等。

我目前有一个用户表,除了注册数据之外,还包含用户在他的钱包中的总余额。

还有另一个交易表,它指示所有已进行的交易、进出账户的资金 (in_or_out)、交易的参考 (trans_ref)以及被转移的价值

以下是当前结构:

|        Table USERS       |
----------------------------
|cod        varchar (index)|
|full_name  varchar        |
|username   varchar        |
|password   varchar        |
|wallet     decimal        |
|created_at timestamp      |
|activate   int            |


|    Table TRANSACTIONS    |
----------------------------
|cod        varchar (index)|
|user_cod   varchar        |
|trans_ref  varchar        |
|in_or_out  int            |
|value      decimal        |
|created_at timestamp      |
|status     int            |

我担心由于交易出错,金额不会添加到用户表中。或者用户进行了支付并且金额没有从表中扣除。因为我会一直考虑用户*钱包*的价值作为他帐户中的总金额。

因此,如果他购买了 1000 美元,而这笔金额没有从他的帐户中扣除,他仍然有相同的金额可以花费,这可能会给公司带来损失,因为有 100 万美元用户,很难知道是哪个用户提出了问题。

我认为,我不是在用户表中计算钱包的总数,而是进行查询以获取交易的总和。那么在这种情况下,如果我有 100 万用户和 10 亿笔交易,那么一直获取汇总的数据就太繁重了,这会给系统查询带来很多缓慢。

有一些计算或类似系统经验的人可以指导我用更好的逻辑来构建这些表格吗?

请记住,当前的结构仍然可以通过任何必要的方式进行修改。

【问题讨论】:

  • 这种事情需要专业的支持

标签: mysql data-structures


【解决方案1】:

首先,我假设 in_or_out 列定义事务是否为入站/出站事务。如果是这种情况,我认为此列是不必要的,因为可以使用十进制数据类型传达相同的信息,因为十进制同时处理正值和负值。展望未来,我将继续假设 in_or_out 列不再出现在图片中。

我认为,为了做到这一点,我们需要真正了解您的用户将在您的应用程序中遵循的流程。展望未来,我将假设您需要能够向您的用户展示可用的资金总额。此外,您还需要验证您的用户是否有足够的资金来处理某些交易。

要向您的用户显示可用资金的总额,我认为在 users 表中提供可用资金总额就可以了。问题是您如何在新交易进入时保持同步,同时关注可扩展性?虽然我不是基础架构方面的专家,但我相信下面列出的解决方案会非常高效(尽管我确信还有进一步改进的空间)

对于交易验证,您只需验证基本上是购买/转账的负面交易。

综上所述,我认为下面列出的 PLSQL 将从数据处理的角度满足您的需求:

-- Function to calculate the total funds available for a single user
CREATE OR REPLACE FUNCTION total_funds (l_cod VARCHAR(100)) -- Guessing about the data type here. You'll need to update as needed.
RETURNS INT

BEGIN

    DECLARE l_total DECIMAL(50, 2); -- Also guessing about the data type here. You'll need to update as needed.

    SELECT 
        SUM(value) INTO l_total
    FROM 
        transactions t
    WHERE
        t.cod = l_cod;

    RETURN l_total;

END;

-- Procedure to calculate total user funds
CREATE OR REPLACE PROCEDURE calc_user_funds (l_cod VARCHAR(100))
BEGIN

    UPDATE 
        users u
    SET 
        u.wallet = total_funds(l_cod)
    WHERE
        u.cod = l_cod;

END;

-- Procedure to validate funds available
CREATE OR REPLACE FUNCTION val_trans (l_cod VARCHAR(100), l_trans_value DECIMAL (100, 2))
RETURNS INT

BEGIN
    DECLARE l_total_avail DECIMAL(10, 2);
    DECLARE result INT;

    SET l_total_avail = total_funds(l_cod);

    IF l_total_avail >= l_trans_value THEN
        SET result = 1;
    ELSE
        SET result = 0;
    END IF;

    RETURN result;

END;

-- Trigger
CREATE TRIGGER trans_insert AFTER INSERT ON transactions
FOR EACH ROW
BEGIN

    -- Evaluate whether or not the transaction is a positive/negative transaction
    IF NEW.in_or_out < 0 THEN -- If transaction is a purchase/negative transaction
        IF val_trans(NEW.cod) = 1 THEN
            -- Do something to indicate that the transaction is approved

        ELSE
            -- Do something to indicate that the transaction is not approved
        END IF;        
    END IF

    CALL calc_user_funds(NEW.cod);

END;

通过这样做,您可以保证事务表中的每个事务都会正确更新您的用户表。这反过来又允许您使用用户表中的总数在您的应用程序中显示,从而无需在每次您的用户只想查看他们的总资金时计算总资金。应该为您节省一些处理...

要处理事务验证,您会看到我添加的触发器将首先评估是否需要进行验证,从而消除更多不必要的处理。根据结果​​,它将采取您必须进一步定义的下一个适当操作。

对于额外的性能改进,我已经看到了几种解决方案,包括数据库复制/负载平衡和跨多个表/数据库的逻辑数据拆分。我敢肯定,还有很多其他选择,具体取决于您的基础设施。不幸的是,这是我的专业知识有限的地方......

希望这个答案足以让您指出正确的方向。

祝你好运!

【讨论】:

  • 我不确定我理解你的意思,但我认为你所说的正是我在上面的例子中所说的。 TRANSACTIONS 表做这样的事情。按照你说的,trans_ref字段等于事务类型,in_or_out表示是输入(正)还是输出(负)。但正如我所说,如果我有很多用户和很多交易,那么这张表中的总和表示用户钱包里有多少可能会变得有点沉重。
  • 对不起,如果我的回答有点模棱两可。我没有意识到你的表已经有一个类型列......基本上我认为你的表结构很好。如果您的桌子变大,我可以理解您对性能的担忧。我已经看到了一些处理这类问题的技术。基本上它们都涉及根据某种逻辑将数据拆分为几个较小的表。
  • 在我有更多时间考虑您的特定问题后,更新了我的答案,使其更加具体。我希望这会有所帮助!
  • 谢谢,这对我来说仍然不是最好的解决方案,但是你的回答对我有很大的帮助
  • 很乐意为您提供帮助!
猜你喜欢
  • 2010-12-21
  • 2011-01-17
  • 1970-01-01
  • 2010-12-18
  • 2011-01-09
  • 2010-11-21
  • 1970-01-01
  • 1970-01-01
  • 2017-09-19
相关资源
最近更新 更多