服务器卡顿导致数据库重复插入怎么解决?

代码因为业务问题就不放了,但是我可以和大家详细说一下代码逻辑
一个方法体{
….//方法的作用是进行数据库查询,检查用户状态并更新
….如果用户为未登记{
……..//一列的业务操作
….}else 如果用户已经登记{
……..//跳出方法,返回信息:用户已经登记,无需再次进行,
….}
….开启事务{
……..进行一系列的操作,并更新用户状态为已经登记
….}
}

现在出现了一个问题,这个问题我尝试了很多次都无法重复,那就是当两个人同时对一个用户进行登记时,按正常流程,第一个脚本执行完后,第二个脚本就会被返回已登记,但是,可能正好是服务器卡了,导致第一个人的脚本未执行到更新用户状态的那一步,第二个脚本就已经执行过了用户状态判断的那一步,导致两个脚本都判断用户为登记,两个脚本最终都执行成功了
所以这个问题要怎么解决,用数据锁吗,如果用锁的话,会对性能造成较大影响吗?

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
最佳答案

update的时候增加一个where条件,比如说

  1. updated_at,不一致不让更新,提示说有人修改过,刷新页面重新编辑
  2. status 状态,状态被修改过或者不符合条件不让更新等等,根据实际业务
10个月前 评论
她来听我的演唱会 8个月前
讨论数量: 14

如果两个脚本同时运行到了事务插入的阶段,锁机制可以解决这个问题吗?第一个事务锁了数据,执行完成之后更新数据并解锁,那第二个脚本检测到数据解锁了,不是就会紧接着再执行一遍吗?

10个月前 评论
徵羽宫 8个月前

重复插入锁能解决。锁处理完释放后去查询就查询不到或者查询到已执行了,脚本执行自然就失效了。

10个月前 评论
sanders

锁可以解决,注意你下面用到了事务,若没有特殊要求应该将行锁查询加入到下面的事务中执行。

10个月前 评论

方案一:加锁
方案二:可以在插入的时候使用 insert ignore ,如果数据已经存在,不会再插入了。
方案三:选择一个用户的唯一标记(例如身份证号,手机号)添加一个唯一索引

10个月前 评论
陈先生

Cache::lock()

10个月前 评论

更新用户状态为已经登记时,使用数据库乐观锁判定是否更新成功,没更新成功把事务回滚掉返回错误

10个月前 评论

悲观锁 ,在事务里面lockForUpdate啥的

10个月前 评论

update的时候增加一个where条件,比如说

  1. updated_at,不一致不让更新,提示说有人修改过,刷新页面重新编辑
  2. status 状态,状态被修改过或者不符合条件不让更新等等,根据实际业务
10个月前 评论
她来听我的演唱会 8个月前

事务里使用 SELECT FOR UPDATE 语句, 应该就没问题。

DB::beginTransaction();
DB::table('users')
        ->where('id', 1)
        ->lockForUpdate()
        ->first();

···

DB::commit();

差不多就是这个样子, 我一般事务里面都是使用 DB Facade 而不是 Eloquent Orm , 主要是为了确保事务和更新语句在同一个上下文,并且使用的是同一个数据库链接。而且如果 Orm 有观察者,操作日志之类的东东,可能会产生意想不到的副作用。

8个月前 评论
徵羽宫 (作者) 8个月前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!