欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

thinkphp6使用mysql悲觀鎖解決商品超賣問(wèn)題的實(shí)現(xiàn)

 更新時(shí)間:2021年11月23日 09:25:37   作者:每天至少八杯水1688  
這篇文章主要介紹了thinkphp6使用mysql悲觀鎖解決商品超賣問(wèn)題的實(shí)現(xiàn)

悲觀鎖介紹(百科):

悲觀鎖,正如其名,它指的是對(duì)數(shù)據(jù)被外界(包括本系統(tǒng)當(dāng)前的其他事務(wù),以及來(lái)自外部系統(tǒng)的事務(wù)處理)修改持保守態(tài)度,因此,在整個(gè)數(shù)據(jù)處理過(guò)程中,將數(shù)據(jù)處于鎖定狀態(tài)。悲觀鎖的實(shí)現(xiàn),往往依靠數(shù)據(jù)庫(kù)提供的鎖機(jī)制(也只有數(shù)據(jù)庫(kù)層提供的鎖機(jī)制才能真正保證數(shù)據(jù)訪問(wèn)的排他性,否則,即使在本系統(tǒng)中實(shí)現(xiàn)了加鎖機(jī)制,也無(wú)法保證外部系統(tǒng)不會(huì)修改數(shù)據(jù))。

使用場(chǎng)景舉例:以MySQL InnoDB為例

商品goods表,假設(shè)商品的id為1,購(gòu)買數(shù)量為1,status為1表示上架中,2表示下架?,F(xiàn)在用戶購(gòu)買此商品,在不是高并發(fā)的情況下處理邏輯是:

  • 查找此商品的信息;
  • 檢查商品庫(kù)存是否大于購(gòu)買數(shù)量;
  • 修改商品庫(kù)存和銷量;

上面這種場(chǎng)景在高并發(fā)訪問(wèn)的情況下很可能會(huì)出現(xiàn)問(wèn)題。如果商品庫(kù)存是100個(gè),高并發(fā)的情況下可能會(huì)有1000個(gè)同時(shí)訪問(wèn),在到達(dá)第2步的時(shí)候,都會(huì)檢測(cè)通過(guò)。這樣會(huì)出現(xiàn)商品庫(kù)存是-900個(gè)的情況。顯然著不滿足需求?。。?/strong>

商品表結(jié)構(gòu):

CREATE TABLE `goods` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(100) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  `status` tinyint(1) NOT NULL DEFAULT '1',
  `total` int(11) NOT NULL DEFAULT '0',
  `sell` int(11) NOT NULL DEFAULT '100',
  `price` decimal(10,2) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
 
INSERT INTO `test`.`goods`(`id`, `name`, `status`, `total`, `sell`, `price`) VALUES (1, '商品', 1, 0, 100, 15.00);

訂單表結(jié)構(gòu):

CREATE TABLE `orders` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `uid` int(11) NOT NULL DEFAULT '0',
  `create_time` datetime NOT NULL,
  `status` tinyint(1) NOT NULL DEFAULT '1',
  `goods_id` int(11) NOT NULL DEFAULT '0',
  `order_no` varchar(200) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

使用悲觀鎖處理。

當(dāng)我們?cè)诓樵兂鰃oods信息后就把當(dāng)前的數(shù)據(jù)鎖定,直到我們修改完畢后再解鎖。那么在這個(gè)過(guò)程中,因?yàn)間oods被鎖定了,就不會(huì)出現(xiàn)有第三者來(lái)對(duì)其進(jìn)行修改了。

注:要使用悲觀鎖,我們必須關(guān)閉mysql數(shù)據(jù)庫(kù)的自動(dòng)提交屬性,因?yàn)镸ySQL默認(rèn)使用autocommit模式,也就是說(shuō),當(dāng)你執(zhí)行一個(gè)更新操作后,MySQL會(huì)立刻將結(jié)果進(jìn)行提交。thinkphp6中使用事務(wù),手動(dòng)進(jìn)行提交回滾。

<?php
 
namespace app\controller;
 
use app\BaseController;
use think\facade\Db;
 
class Test extends BaseController
{
 
    /**
     * 不加鎖
     * @return string|void
     */
    public function test_1()
    {
        $num = 1;
        $goods_id = 1;
        Db::startTrans();
        try {
            $where = [];
            $where['id'] = $goods_id;
            $where['status'] = 1;
            $goods_info = Db::table('goods')->where($where)->find();
            if (empty($goods_info)) {
                return '商品不存在';
            }
            $total = $goods_info['total'];
            $sell = $goods_info['sell'];
            if ($total < $num) {
                return '庫(kù)存不足';
            }
            $data['total'] = $total-$num;
            $data['sell'] = $sell+$num;
            $res = Db::table('goods')->where(['id'=>$goods_id])->update($data);
            $order_data = [];
            $order_data['uid'] = rand(1000,9999);
            $order_data['status'] = 1;
            $order_data['create_time'] = date('Y-m-d H:i:s');
            $order_data['goods_id'] = $goods_id;
            $order_data['order_no'] = date('YmdHis').rand(1000,10000);
            $order_res = Db::table('orders')->insert($order_data);
            Db::commit();
        } catch (\Exception $e) {
            // 回滾事務(wù)
            Db::rollback();
            echo $e->getMessage();
            exit('rollback');
        }
        echo '請(qǐng)求成功';
    }
 
    /**
     * 加鎖--悲觀鎖
     * @return string|void
     */
    public function test_2()
    {
        $num = 1;
        $goods_id = 1;
        Db::startTrans();
        try {
            $where = [];
            $where['id'] = $goods_id;
            $where['status'] = 1;
            $goods_info = Db::table('goods')->lock(true)->where($where)->find();
            if (empty($goods_info)) {
                return '商品不存在';
            }
            $total = $goods_info['total'];
            $sell = $goods_info['sell'];
            if ($total < $num) {
                return '庫(kù)存不足';
            }
            $data['total'] = $total-$num;
            $data['sell'] = $sell+$num;
            $res = Db::table('goods')->where(['id'=>$goods_id])->update($data);
            $order_data = [];
            $order_data['uid'] = rand(1000,9999);
            $order_data['status'] = 1;
            $order_data['goods_id'] = $goods_id;
            $order_data['order_no'] = date('YmdHis').rand(1000,10000);
            $order_data['create_time'] = date('Y-m-d H:i:s');
            $order_res = Db::table('orders')->insert($order_data);
            Db::commit();
        } catch (\Exception $e) {
            // 回滾事務(wù)
            Db::rollback();
            echo $e->getMessage();
            exit('rollback');
 
        }
        echo '請(qǐng)求成功';
    }
 
}

使用jmeter工具測(cè)試,創(chuàng)建線程測(cè)試組:

關(guān)于使用jmeter創(chuàng)建測(cè)試高并發(fā)例子,可查看:使用JMeter進(jìn)行高并發(fā)測(cè)試_左右..的博客-CSDN博客_jmeter高并發(fā)測(cè)試

這里模擬1s內(nèi)1000個(gè)用戶同時(shí)訪問(wèn)

?創(chuàng)建http請(qǐng)求:

添加察看結(jié)果樹(shù):

?測(cè)試開(kāi)始:

100個(gè)商品不加鎖的結(jié)果:

100個(gè)商品庫(kù)存,生成訂單187個(gè),超賣87個(gè)商品,這在項(xiàng)目開(kāi)發(fā)中是絕對(duì)不允許的。

100個(gè)商品,加鎖結(jié)果:

?加鎖,得到解決。

到此這篇關(guān)于thinkphp6使用mysql悲觀鎖解決商品超賣問(wèn)題的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)thinkphp6 商品超賣內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于PHP-FPM進(jìn)程池探秘

    基于PHP-FPM進(jìn)程池探秘

    下面小編就為大家?guī)?lái)一篇基于PHP-FPM進(jìn)程池探秘。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • PHP實(shí)現(xiàn)微信申請(qǐng)退款功能

    PHP實(shí)現(xiàn)微信申請(qǐng)退款功能

    這篇文章主要為大家詳細(xì)介紹了PHP實(shí)現(xiàn)微信申請(qǐng)退款功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下方法
    2018-10-10
  • YII框架行為behaviors用法示例

    YII框架行為behaviors用法示例

    這篇文章主要介紹了YII框架行為behaviors用法,結(jié)合實(shí)例形式分析了Yii框架行為behaviors的添加與使用簡(jiǎn)單操作技巧,需要的朋友可以參考下
    2019-04-04
  • Yii框架操作cookie與session的方法實(shí)例詳解

    Yii框架操作cookie與session的方法實(shí)例詳解

    這篇文章主要介紹了Yii框架操作cookie與session的方法,結(jié)合實(shí)例形式詳細(xì)分析了Yii針對(duì)cookie與session操作的常用方法及相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2019-09-09
  • windows下apache搭建php開(kāi)發(fā)環(huán)境

    windows下apache搭建php開(kāi)發(fā)環(huán)境

    本文詳細(xì)介紹了在Windows2003下使用Apache2.2.21/PHP5.3.5/Mysql5.5.19/phpMyAdmin3.4.9搭建php開(kāi)發(fā)環(huán)境,本文介紹的非常詳細(xì),需要的朋友快來(lái)學(xué)習(xí)吧
    2015-08-08
  • 清除laravel緩存命令代碼實(shí)例

    清除laravel緩存命令代碼實(shí)例

    這篇文章主要介紹了清除laravel緩存命令代碼實(shí)例,這個(gè)是在應(yīng)用終端中直接命令清除,有感興趣的同學(xué)可以學(xué)習(xí)下
    2021-03-03
  • Ubuntu 16.04中Laravel5.4升級(jí)到5.6的步驟

    Ubuntu 16.04中Laravel5.4升級(jí)到5.6的步驟

    這篇文章主要給大家介紹了關(guān)于在Ubuntu 16.04中Laravel5.4升級(jí)到5.6的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-12-12
  • 8個(gè)必備的PHP功能實(shí)例代碼

    8個(gè)必備的PHP功能實(shí)例代碼

    本文將分享8個(gè)開(kāi)發(fā)必備的PHP功能,個(gè)個(gè)都非常實(shí)用:傳遞任意數(shù)量的函數(shù)參數(shù) 、使用glob()查找文件、獲取內(nèi)存使用情況信息、獲取CPU使用情況信息 、獲取系統(tǒng)常量 、生成唯一的id 、序列化 、字符串壓縮。很實(shí)用的8個(gè)PHP功能。
    2013-10-10
  • linux實(shí)現(xiàn)php定時(shí)執(zhí)行cron任務(wù)詳解

    linux實(shí)現(xiàn)php定時(shí)執(zhí)行cron任務(wù)詳解

    linux實(shí)現(xiàn)php定時(shí)執(zhí)行cron任務(wù)
    2013-12-12
  • Laravel5.1 框架登錄和注冊(cè)實(shí)現(xiàn)方法詳解

    Laravel5.1 框架登錄和注冊(cè)實(shí)現(xiàn)方法詳解

    這篇文章主要介紹了Laravel5.1 框架登錄和注冊(cè)實(shí)現(xiàn)方法,結(jié)合實(shí)例形式詳細(xì)分析了laravel5.1框架登錄與注冊(cè)相關(guān)配置、路由、實(shí)現(xiàn)方法與操作注意事項(xiàng),需要的朋友可以參考下
    2020-01-01

最新評(píng)論