V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MySQL 5.5 Community Server
MySQL 5.6 Community Server
Percona Configuration Wizard
XtraBackup 搭建主从复制
Great Sites on MySQL
Percona
MySQL Performance Blog
Severalnines
推荐管理工具
Sequel Pro
phpMyAdmin
推荐书目
MySQL Cookbook
MySQL 相关项目
MariaDB
Drizzle
参考文档
http://mysql-python.sourceforge.net/MySQLdb.html
abcbuzhiming
V2EX  ›  MySQL

想问问大家是怎么设计支付记录数据表的?

  •  
  •   abcbuzhiming · 2017-06-06 10:54:21 +08:00 · 7696 次点击
    这是一个创建于 2718 天前的主题,其中的信息可能已经有所发展或是发生改变。
    一般来讲,现在一家网站往往会支持好几家的支付,少点的 4-5 家,多点的七八家有可能。那么,因为每家支付通知的数据结构不一样,所以从理论上,应该一家支付就拥有专门的一张表用于记录支付他家的数据;然后为了统计方便,你还需要额外一张表记录网站上所有用户的支付行为,在这张支付行为表里,只会以用户 id 为索引记录用户进行了其中一家的支付,并记录这条支付记录 id (指向具体支付表记录里的记录)。

    这种设计的冗余数据很少,但是缺点就是,你按用户 id 查支付记录时候如果要查到详细信息(比如这条支付到底支付了多少钱,买了什么东西),就必须再次进行查询,不能用简单的联表查询来解决这个问题,因为你支付方式有多家,你光联表一次不能查到全部记录。

    这个问题大家有没有什么好点的办法
    14 条回复    2017-06-06 23:19:33 +08:00
    doing
        1
    doing  
       2017-06-06 11:20:58 +08:00
    我觉得啊,对你的系统来说,支付重点考虑调用 api 是否成功,进行业务逻辑处理吧,应该不需要考虑”一家支付就拥有专门的一张表用于记录支付他家的数据“,就算有,也应该是自己抽取关键相关字段数据设计表保存。这张表也不应该涉及到”比如这条支付 xxx 买了什么东西“
    abcbuzhiming
        2
    abcbuzhiming  
    OP
       2017-06-06 11:45:56 +08:00
    @doing 一家支付拥有专门一张表记录他家的信息有两个目的,其中一个就是你说的 api 调用是否成功,因为支付的模式基本都是支付商向你的服务器推送支付成功 /失败信息,你不记录这条信息,你咋知道这条支付是否已经处理过呢(支付商有时候会多次推送)。另外一个就是用于明细查询和对账,特别是对账时要求记录该支付推送过来的信息的全部,越详细越好,这就是为啥每家支付都专门给一张表的原因。

    最后你说的问题就是我遇到的问题,不记录这条支付买了什么东西,那么查的时候你就得联表了
    owenliang
        3
    owenliang  
       2017-06-06 12:17:13 +08:00 via Android
    我的做法是订单存两份,以用户维度为主表(按 uid 取模),数据实时同步到商家维度的辅表(按 poi 取模)。
    doing
        4
    doing  
       2017-06-06 12:34:28 +08:00
    @abcbuzhiming 按你这样的业务,是需要一种支付一张表啊。第二,联表是肯定,你不可能把买了什么东西也放入到这个单独的支付表里面,买什么东西应该是你系统本身的业务数据(属于账单的关联数据,支付应该和账单有直接关系,和账单的关联数据无直接关系)。
    shinwood
        5
    shinwood  
       2017-06-06 12:39:11 +08:00 via iPhone
    一张支付记录表
    一张支付方式索引表
    一张账单索引表
    一张账单明细表
    abcbuzhiming
        6
    abcbuzhiming  
    OP
       2017-06-06 13:45:41 +08:00
    @owenliang 没理解你的意思,用户维度的主表好理解,我也有这张表,取摸是什么意思呢,商家维度的辅助表不止一张的
    abcbuzhiming
        7
    abcbuzhiming  
    OP
       2017-06-06 13:48:32 +08:00
    @doing 我这种模式面对的问题是,光联表解决不了问题,比如我按用户维度查询出了 30 条记录,这 30 条记录里,有用微信支付,有支付宝,还有银联的,你怎么联表查出具体的支付信息呢,left join 只能在纵向上连接一张表,而我需要在纵向上连接好几张表
    abcbuzhiming
        8
    abcbuzhiming  
    OP
       2017-06-06 13:49:49 +08:00
    @shinwood 你把多个支付方式的详情记录在一张表里,那这张表不同类型支付信息之间冗余数据很多啊
    sunchen
        9
    sunchen  
       2017-06-06 13:57:13 +08:00
    辅表的建立 我觉得一种方式是建立一个超宽的表,把各个数据源的字段全填进去,这个样所有支付渠道结果都在一个表里。另一种方案就是用 json 存储非结构话数据,如果你用的 postgres,强烈建议使用方案二
    3dwelcome
        10
    3dwelcome  
       2017-06-06 14:00:00 +08:00
    这就是个权衡的问题,个人选择冗余数据多。相对而言,设计还是简单点,便于维护,当程序员久了,你就会觉得写复杂代码是件很容易的事,但要把一大坨代码维护好,就相当困难。

    ps: wiki 上有个叫 graph database 的东西,就是用来处理 SQL 无法表述完善的网状关系结构,查询一个主节点,自动带出相关节点,和你这个需求有点接近,后端是 no-sql 的。
    Fishdrowned
        11
    Fishdrowned  
       2017-06-06 14:09:59 +08:00 via Android
    主表 orders,放订单号,金额,用户 id,支付方式,状态,创建时间,支付网关订单号,成功时间,取消时间,关闭时间,等等,通用,而且真正重要的字段。
    附表 order_data,订单号加一个 json 字段,放各种乱七八糟又不统一信息,同时把订单状态更新记录也塞进这里。
    然后再开两个表,放 api 发出,以及接受请求的流水记录。

    以上四个表应该足够你倒腾了,不要一种支付方式开一个表。

    再说你收到回调要判断怎么处理,那是主表的事(看订单状态),而不是接受记录的事。
    doing
        12
    doing  
       2017-06-06 14:12:04 +08:00
    @abcbuzhiming 有用微信支付,有支付宝,还有银联的。。。这个不可以变成一个“虚拟的大表”吗,毕竟一个账单支付成功,手段是唯一的。
    leeg810312
        13
    leeg810312  
       2017-06-06 20:36:50 +08:00 via Android
    若每种支付一张表,按用户查询所有支付数据就必须关联所有支付表,实质效果就是一张大表,还不如全部支付明细存在一张表,还减少了关联呢,而且要是增加支付方式,要关联更多的表,相关 sql 也都要改,维护也很麻烦。
    0915240
        14
    0915240  
       2017-06-06 23:19:33 +08:00
    一张表存储、重要基本信息各家提取出来各存字段,其他‘冗余’的详细信息,另存 json 字段。

    上 pg 或者 5.7 的 mysql .
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5703 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 01:40 · PVG 09:40 · LAX 17:40 · JFK 20:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.