shenmeshibanjiao
V2EX  ›  PHP

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

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

    出现负数是因为脏读了。
    Sikoay
        14
    Sikoay  
       Oct 31, 2017 via Android
    事务判断余额是不是就能解决余额为负
    silentoy
        15
    silentoy  
       Oct 31, 2017
    @shenmeshibanjiao 如果余额是通过 API 获取的话,确实如 @klgd 所说,事务的控制应该是在上游的余额 API 端控制了,你这边很难处理
    klgd
        16
    klgd  
       Oct 31, 2017
    @shenmeshibanjiao #8 “转账”是指请求 API 去扣余额吗?
    你这个逻辑设计的有问题啊,如果你这边失败了,扣余额成功了怎么办?
    irory
        17
    irory  
       Oct 31, 2017
    来一发分布式锁 ,比如 redis lock,就能解决了呀 !
    FYK
        18
    FYK  
       Oct 31, 2017 via iPhone
    @abcfyk。。。好巧
    shenmeshibanjiao
        19
    shenmeshibanjiao  
    OP
       Nov 1, 2017
    @klgd 老哥,那该怎么弄~
    klgd
        20
    klgd  
       Nov 1, 2017
    @shenmeshibanjiao #19 我不清楚你们的余额是什么概念,为什么下订单时扣除,有没有可能在订单过程中不与余额交互,然后在其他逻辑里处理余额
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   3406 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 79ms · UTC 10:56 · PVG 18:56 · LAX 03:56 · JFK 06:56
    ♥ Do have faith in what you're doing.