并发下单遇到问题记录

1、问题描述

平台直播时,遇到超买情况,即使事务中查库存加了for update锁,仍然出现超买情况。超买:库存剩余2个,生成订单多于2笔

2、排查问题

(1)并发压测

使用ab工具并发压测

ab -c 100 -n 100 xxx

(2)事务相关报错

记录错误日志有报错,貌似事务不存在

[42000]SQLSTATE[42000]: Syntax error or access violation: 1305 SAVEPOINT trans2 does not exist[/data/www_code/dev/zz/smart_fenxiao/smart_crmeb/vendor/topthink/think-orm/src/db/PDOConnection.php:1402]

网上搜索出现原因,解决方案,很少解答,有英文解答,大致原因是事务嵌套导致的,找不到事务提交或者回滚节点。

检查代码,发现业务层加了事务,手动事务内部,涉及多个model更新插入数据部分,TP6框架底层Model新增,更新数据方法用到了事务。
猜测1,可能是在model层有事务提交,导致整个事务提交,业务层加的事务自动提交则会找不到事务节点。
猜测2, 有事务嵌套,事务内部有报错,回滚代码找不到对应事务

解决:使用DB的插入更新数据代替model的使用(注:model层的方法也是使用DB方式,只不过方法中又加了事务逻辑,model层insert 相关方法直接是继承DB的,可直接用model调用,update被model层方法重写,不可直接使用)

(3)并发死锁报错

上述问题解决后,继续压测,有SQL报错

SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction

经过记录执行日志,排查到产生死锁的位置,生成订单记录时,订单表加了唯一索引,逻辑原因,并发产生字段不唯一性,导致产生死锁

解决:数据库唯一索引去掉,因为逻辑中足以保证字段唯一性

3、总结

(1)结果

最终压测超买问题没有出现。验证:去掉for update 锁,压测会出现多于库存的订单

(2)排查问题总结

  • thinkphp6中model的creaete,update相关方法有坑啊,竟然有隐藏事务
  • 排查问题,多打日志,异常日志等,特别是压测时,不会有直接结果输出,应记录日志观察数据结果
  • 并发测试,库存100,ab测试,-c 100 -n 100 并发100,完成请求数100,而会有部分请求失败(挺多),估计是唯一索引导致的失败,而事务会回滚,因为事务嵌套,导致事务保存点丢失报错。解决了几个问题后,没有出现超买问题,应该与所述问题有关系,至于详细原因,待分析排查。
  • 并发测试工具可以用ab, wrk(网上说wrk性能更好点)
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值