Laravel中自增实现方案
admin
2023-01-19 21:00:59
0

工作中经常会对一列数据进行自增操作,设想一个场景。
总共发放10张优惠券(以下的操作以时间为序列)
1)用户1请求领取1张优惠券;
2)进程1查询到数据库中剩余10张,代码更新优惠券数量,此时为内存中优惠券数量为9;
3)此时,用户2请求领取1张优惠券。进程1并未将9写入到数据库中,所以此时进程2取到的优惠券的数量还是10。进程2计算数量,内存中的优惠券数量为9;
4)进程1更新数据库优惠券的数量,number = 9;
5)进程2更新数据库优惠券的数量,number = 9;
实际上已经发出去了两张优惠券,但是数据库中还剩9张优惠券。

所以呢,将数据load到内存中加减完成再入库是有点风险的。
两种解决方案:
1)加锁,别管是加个乐观锁还是悲观锁,这个不细聊了;
2)不在内存中加,直接在数据库层面进行set number = number - 1;在Laravel中,有increment和decrement封装来实现操作。
increment:

public function increment($column, $amount = 1, array $extra = [])
{
        if (! is_numeric($amount)) {
                throw new InvalidArgumentException('Non-numeric value passed to increment method.');
        }
        $wrapped = $this->grammar->wrap($column);
        $columns = array_merge([$column => $this->raw("$wrapped + $amount")], $extra);
        return $this->update($columns);
}

decrement:

public function decrement($column, $amount = 1, array $extra = [])
{
        if (! is_numeric($amount)) {
                throw new InvalidArgumentException('Non-numeric value passed to decrement method.');
        }
        $wrapped = $this->grammar->wrap($column);
        $columns = array_merge([$column => $this->raw("$wrapped - $amount")], $extra);
        return $this->update($columns);
}

都调用了update方法,看一下update:

public function update(array $values)
    {
        $sql = $this->grammar->compileUpdate($this, $values);
        var_dump($sql); // 打印一下sql语句
        return $this->connection->update($sql, $this->cleanBindings(
            $this->grammar->prepareBindingsForUpdate($this->bindings, $values)
        ));
    }

用两种方式进行数据库修改:
1)直接修改数量

$res = self::where('id', $data['id'])->update(['number' => self::raw('number + 1')] );

查看输出的sql语句:

 update  coupon  set  number  =  ?  where  id  = ?

2)用decrement

$res = self::where('id', $data['id'])->decrement('number', 2);

查看sql输出结果:

update coupon set number = number - 2 where id = ?;

所以并发较多的情况下建议使用increment和decrement。

相关内容

热门资讯

腾讯QQ正式接入OpenCla... 3月7日,腾讯宣布为QQ新增AI生态能力,用户现可通过官方渠道将OpenClaw智能体接入QQ机器人...
四川尔润取得新型玄武岩纤维防眩... 国家知识产权局信息显示,四川尔润玄武岩纤维科技有限公司取得一项名为“一种新型玄武岩纤维防眩板”的专利...
伊朗总统称停止攻击周边国家,讲... 当地时间3月7日,伊朗总统佩泽希齐扬发表讲话,向邻国表示歉意,并表示临时领导委员会6日批准,不再攻击...
折叠屏影像冠军!荣耀Magic... 快科技3月7日消息,荣耀Magic V6将于3月10日在国内发布,今天官方预热称其为折叠屏影像冠军。...
印度:同意伊朗紧急请求 【环球网报道 记者 姜蔼玲】伊朗军舰日前在斯里兰卡附近海域遭美国潜艇击沉,引发外界关注。据路透社报道...
美精锐空降兵突然取消演习,美国... 【文/观察者网 阮佳琪】美军突然取消精锐部队演习,进一步引发外界对其中东兵力部署的猜测。当地时间6日...
特朗普先“赢”上了:伊朗道歉都... 当地时间3月7日,针对伊朗总统佩泽希齐扬向其邻国公开致歉一事,美国总统特朗普又在社交媒体上“大赢特赢...
新任中国驻阿联酋大使赴机场为回... 【环球时报-环球网报道 记者 张志文】3月7日,新任中国驻阿联酋大使曾继新抵阿后即赴迪拜国际机场为搭...
全国人大代表雷军:京津冀联建国... 新京报讯(记者曹晶瑞)“以科技创新加快引领新质生产力,是时代赋予我们这代人的使命,民营企业更要敢为人...
特朗普说结束伊朗战争后“古巴只... 特朗普3月5号下午说,结束伊朗战争之后,古巴只是时间问题,他此番表态背后真实目的又是什么?对此,国际...