吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1126|回复: 17
收起左侧

[求助] mysql事务请教

[复制链接]
ppgjx 发表于 2022-11-1 17:11
我现在遇到一个支付回调问题 我得写法是
1.用户提交订单 订单表生成一条订单记录 并有个state字段标识该订单未支付
2.等到用户支付成功后,微信那边回调到我服务器,会带这个订单id,然后我根据state判断这个订单是否已经支付,如果没有支付就改为支付状态,并发放奖励

现在有个问题来了 并发问题

假如微信服务器一次性回调了两次支付成功请求 而且都是同一个订单id 我们可以理解为两个请求 分别用a,b表示

首先a请求过来了 他查询这个订单id发现订单没有支付 进行支付处理 但是由于某种原因 阻塞了2秒 只读取了数据库  这时候b请求过来了 很顺利的把这个订单处理了奖励也发放了 表state也更新为了已支付, 这时候a请求不阻塞了但是他读取的到订单状态还是未支付 它又进行了一次更新操作并又下发了奖励

这就导致发放了两次奖励 这种问题怎么解决呢?

我启动了mysql事务 好像没有用 还是会发放两次奖励






发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Goldrepo 发表于 2022-11-1 17:22
1.给更新订单状态的方法加锁;
2.更新订单状态时加上订单状态条件,eg:update xxx set status = 1 where id = xxx and status = 0;这样就算同时两个请求过来了,优先执行更新的能正常执行,后更新的会因为状态条件变了而update为0;一旦更新条数为0,则不发放奖励

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
ppgjx + 1 + 1 热心回复!

查看全部评分

gaoxiyang1237 发表于 2022-11-1 17:23
这个一般事务控制不了的,应该用分布式锁控制,在操作数据库之前控制加锁。常见有Zookeeper 与redis分布式锁。推荐使用redis分布式锁,对订单号加锁,redis底层是单线程,故不会存在多个线程线程同时操作相同代码(同一个订单)逻辑的问题。具体redis锁实现步骤。百度一下有很多很成熟的方案
stevenliy 发表于 2022-11-1 17:28
Goldrepo 发表于 2022-11-1 17:22
1.给更新订单状态的方法加锁;
2.更新订单状态时加上订单状态条件,eg:update xxx set status = 1 where  ...

沙发正解
石淞元 发表于 2022-11-1 17:29
同意楼上说法,mysql事务不可能控制这个事务问题
吨吨吨吨 发表于 2022-11-1 17:31
注解式事务加在controller上试试,不行就再试试声明式事务
潇洒三叔 发表于 2022-11-1 17:37
乐观锁 可以解决
还来得及。 发表于 2022-11-1 17:43
给发放奖励加个锁,然后发放奖励事件去判断id and state and 锁
13677661413 发表于 2022-11-1 19:07
数据库自带的事务不好解决,可以使用redis对订单进行加锁。不过看你的描述,没涉及到分布式事务,这样的话就用楼上的解决方式:更新数据状态的时候加个乐观锁。
微笑丶永远 发表于 2022-11-1 19:32
沙发正解
没毛病
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 05:41

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表