PHP +mysql 应用怎么防止重复插入 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
shenmeshibanjiao
V2EX    PHP

PHP +mysql 应用怎么防止重复插入

  •  
  •   shenmeshibanjiao 2017-10-31 16:13:00 +08:00 4395 次点击
    这是一个创建于 2954 天前的主题,其中的信息可能已经有所发展或是发生改变。
    1、我有一个 API,可以转账发红包之类的,余额是调用别人的 API 获取的,她的 API 没有判断是否余额充足,所以可能出现负数的情况。所以每次操作是我通过调用他的余额的 API 去判断当前操作是否是 余额充足的。
    2、APP 端快速点击的时候,可能会出现负数的情况,数据库插入了很多时间戳相同的记录。
    这种情况应该怎么解决呀。
    20 条回复    2017-11-01 16:47:28 +08:00
    tradzero
        1
    tradzero  
       2017-10-31 16:53:41 +08:00
    有个很丑的实现 app 端请求的时候把时间戳带上 然后后端请求完成之后把这个时间戳放到 cache 里 然后每次这个 api 请求的时候判断时间戳在不在 cache 里 如果在就直接返回失败 这样就可以避免快速点击的问题 至于防止重复插入 由于你没办法查询余额是否充足.. 理论上是没什么办法避免的吧
    abcfyk
        2
    abcfyk  
       2017-10-31 16:57:51 +08:00
    1. 前端应有请求队列。
    2. 后端所有这种和钱有关的,全部上事务
    shenmeshibanjiao
        3
    shenmeshibanjiao  
    OP
       2017-10-31 17:02:10 +08:00
    @abcfyk 这个订单表都是用了事务的。我大概的流程是这样的,判断交易密码、调用 API 获取余额,判断余额是否充足,之后开启事务、生成订单、然后再是转账 成功了在 commit 否则就 rollback .但是现在还是有现在的情况的,连续点击多次请求,多条订单记录,余额可能出现负数。
    shenmeshibanjiao
        4
    shenmeshibanjiao  
    OP
       2017-10-31 17:03:04 +08:00
    @tradzero 谢谢老哥,我看我的订单表的时间戳都是一样的- -.
    tabris17
        5
    tabris17  
       2017-10-31 17:07:20 +08:00
    使用 token。一动作一令牌
    klgd
        6
    klgd  
       2017-10-31 17:08:10 +08:00
    余额是在哪个环节扣的?
    另外 上游 API 有问题 你作为下游应用也不可能保证没问题的
    qiuyk
        7
    qiuyk  
       2017-10-31 17:09:26 +08:00
    shenmeshibanjiao
        8
    shenmeshibanjiao  
    OP
       2017-10-31 17:09:26 +08:00
    @klgd 我大概的流程是这样的,判断交易密码、调用 API 获取余额,判断余额是否充足,之后开启事务、生成订单、然后再是转账 成功了在 commit 否则就 rollback .
    silentoy
        9
    silentoy  
       2017-10-31 17:10:20 +08:00
    @shenmeshibanjiao 金额字段应该设置成无符号的,这样 update 的时候如果金额小于订单金额就会失败,从而触发 rollback
    R18
        10
    R18  
       2017-10-31 17:11:49 +08:00
    我觉得这应该是他解决的问题不应该是你
    Redis incr 不知可否解决你的问题
    mahone3297
        11
    mahone3297  
       2017-10-31 17:12:23 +08:00
    @abcfyk 都说了,请求队列。那就不可能出现为负数的情况。
    你应该,每次处理转账的时候,都去请求判断余额。[请求判断余额,扣减]这整个是一个事务,这是一个原子。
    shenmeshibanjiao
        12
    shenmeshibanjiao  
    OP
       2017-10-31 17:13:42 +08:00
    @silentoy 因为余额都是获取 API 的,所以我的数据库是没有存储余额的,这样的话我是否可以尝试一下增加余额,每次操作之后再去获取余额存进去 ^_^ ,谢谢老哥。
    SP00F
        13
    SP00F  
       2017-10-31 17:14:04 +08:00
    开了事务的话,检查一下事务级别。把事务级别调整一下再测试。

    出现负数是因为脏读了。
    Sikoay
        14
    Sikoay  
       2017-10-31 17:14:37 +08:00 via Android
    事务判断余额是不是就能解决余额为负
    silentoy
        15
    silentoy  
       2017-10-31 17:18:10 +08:00
    @shenmeshibanjiao 如果余额是通过 API 获取的话,确实如 @klgd 所说,事务的控制应该是在上游的余额 API 端控制了,你这边很难处理
    klgd
        16
    klgd  
       2017-10-31 17:31:43 +08:00
    @shenmeshibanjiao #8 “转账”是指请求 API 去扣余额吗?
    你这个逻辑设计的有问题啊,如果你这边失败了,扣余额成功了怎么办?
    irory
        17
    irory  
       2017-10-31 17:37:11 +08:00
    来一发分布式锁 ,比如 redis lock,就能解决了呀 !
    FYK
        18
    FYK  
       2017-10-31 17:40:28 +08:00 via iPhone
    @abcfyk。。。好巧
    shenmeshibanjiao
        19
    shenmeshibanjiao  
    OP
       2017-11-01 11:42:49 +08:00
    @klgd 老哥,那该怎么弄~
    klgd
        20
    klgd  
       2017-11-01 16:47:28 +08:00
    @shenmeshibanjiao #19 我不清楚你们的余额是什么概念,为什么下订单时扣除,有没有可能在订单过程中不与余额交互,然后在其他逻辑里处理余额
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1152 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 23:36 PVG 07:36 LAX 15:36 JFK 18:36
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86