欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

用了数据库事务,并发状态下还是出现记录为负值

程序员文章站 2022-04-07 12:46:45
...
比如秒杀某个奖品,奖品数量为1 ,5 个人同时请求, 有一个请求成功后,把数据库值更改为0,接着进行其他后续操作, 然后提交事务,其他4个请求时会提示精品已发完

代码


现在是这样,如果在所有操作处理完成后,在提交事务, 执行并发请求后,奖品的数量更改成负数了,如果在奖品数量更新后,就提交事务,其他的操作,在开启另外一个事务,在并发请求时,则奖品的数量更新不会出现负数, 但是如果这样做,在其他操作处理完成以后,有出现失败的情况,就需要手动回滚 先前更新的奖品数量,请教一下大家可能是什么原因,是因为事务处理的逻辑过长了吗,如果是这样,对于较长的业务逻辑,应该怎么运用事务


回复讨论(解决方案)

mysql 是默认自动提交事务的,即每条 sql 指令都 COMMIT
你需要主动的关闭这一行为

事务处理时,相关的 sql 指令被隔离在一个副本中,所以是相对独立的
但这并不意味其他的连接不能做数据操作

所以,事务只能保证本次链接中的操作的完备性,并不能控制其他连接的操作

事务开始计数器减一如果计数器为负:回滚,退出其他操作提交


其实用不用事务都一样
计数器减一如果计数器为负:计数器加一,退出其他操作

mysql 是默认自动提交事务的,即每条 sql 指令都 COMMIT
你需要主动的关闭这一行为

事务处理时,相关的 sql 指令被隔离在一个副本中,所以是相对独立的
但这并不意味其他的连接不能做数据操作

所以,事务只能保证本次链接中的操作的完备性,并不能控制其他连接的操作

事务开始计数器减一如果计数器为负:回滚,退出其他操作提交


其实用不用事务都一样
计数器减一如果计数器为负:计数器加一,退出其他操作


请问一下这里的计数器说的是 数据库里奖品的数量是吗?
如果是的话

我也是这么判断的
开启事务
如果数量为负数 则回滚退出 否则 数量 -1
其他操作
提交


模拟并发请求我用的是 curl_multi_init 比如数量还剩下1个 模拟请求5次, 数量就变成-4 了

是的,但你是这么描述的
if(奖品数量 提交事务
return ;
}
奖品数量-1;
* 其它后续操作

奖品数量-1; 后你并没有说要判定他的合法性

是的,但你是这么描述的
if(奖品数量 提交事务
return ;
}
奖品数量-1;
* 其它后续操作

奖品数量-1; 后你并没有说要判定他的合法性



这么判断

if(奖品数量-1 回滚,退出
}
奖品数量-1

并发请求还是会减成负数

奖品数量-1 要真实发生后,才可以判断是否小于0

update tbl_name set prize=prize-1
select prize from tbl_name
if prize ROOLBACK
endif

奖品数量-1 要真实发生后,才可以判断是否小于0

update tbl_name set prize=prize-1
select prize from tbl_name
if prize ROOLBACK
endif



谢谢版主耐心的回答,问题解决了,并发的扣减不变成负数了, 原来一直以为 先判断 再减 和 先减再判断效果是一样的