国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - PHP教程 - thinkphp6使用mysql悲觀鎖解決商品超賣問題的實現

thinkphp6使用mysql悲觀鎖解決商品超賣問題的實現

2021-11-29 15:22每天至少八杯水1688 PHP教程

這篇文章主要介紹了thinkphp6使用mysql悲觀鎖解決商品超賣問題的實現,感興趣的可以了解一下

悲觀鎖介紹(百科):

悲觀鎖,正如其名,它指的是對數據被外界(包括本系統當前的其他事務,以及來自外部系統的事務處理)修改持保守態度,因此,在整個數據處理過程中,將數據處于鎖定狀態。悲觀鎖的實現,往往依靠數據庫提供的鎖機制(也只有數據庫層提供的鎖機制才能真正保證數據訪問的排他性,否則,即使在本系統中實現了加鎖機制,也無法保證外部系統不會修改數據)。

使用場景舉例:以MySQL InnoDB為例

商品goods表,假設商品的id為1,購買數量為1,status為1表示上架中,2表示下架。現在用戶購買此商品,在不是高并發的情況下處理邏輯是:

  • 查找此商品的信息;
  • 檢查商品庫存是否大于購買數量;
  • 修改商品庫存和銷量;

上面這種場景在高并發訪問的情況下很可能會出現問題。如果商品庫存是100個,高并發的情況下可能會有1000個同時訪問,在到達第2步的時候,都會檢測通過。這樣會出現商品庫存是-900個的情況。顯然著不滿足需求!!!

商品表結構:

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);

訂單表結構:

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;

使用悲觀鎖處理。

當我們在查詢出goods信息后就把當前的數據鎖定,直到我們修改完畢后再解鎖。那么在這個過程中,因為goods被鎖定了,就不會出現有第三者來對其進行修改了。

注:要使用悲觀鎖,我們必須關閉mysql數據庫的自動提交屬性,因為MySQL默認使用autocommit模式,也就是說,當你執行一個更新操作后,MySQL會立刻將結果進行提交。thinkphp6中使用事務,手動進行提交回滾。

<?php
 
namespace appcontroller;
 
use appBaseController;
use thinkfacadeDb;
 
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 "庫存不足";
            }
            $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) {
            // 回滾事務
            Db::rollback();
            echo $e->getMessage();
            exit("rollback");
        }
        echo "請求成功";
    }
 
    /**
     * 加鎖--悲觀鎖
     * @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 "庫存不足";
            }
            $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) {
            // 回滾事務
            Db::rollback();
            echo $e->getMessage();
            exit("rollback");
 
        }
        echo "請求成功";
    }
 
}

使用jmeter工具測試,創建線程測試組:

關于使用jmeter創建測試高并發例子,可查看:使用JMeter進行高并發測試_左右..的博客-CSDN博客_jmeter高并發測試

這里模擬1s內1000個用戶同時訪問

thinkphp6使用mysql悲觀鎖解決商品超賣問題的實現

 創建http請求:

thinkphp6使用mysql悲觀鎖解決商品超賣問題的實現

添加察看結果樹:

thinkphp6使用mysql悲觀鎖解決商品超賣問題的實現

 測試開始:

100個商品不加鎖的結果:

thinkphp6使用mysql悲觀鎖解決商品超賣問題的實現

100個商品庫存,生成訂單187個,超賣87個商品,這在項目開發中是絕對不允許的。

100個商品,加鎖結果:

thinkphp6使用mysql悲觀鎖解決商品超賣問題的實現

 加鎖,得到解決。

到此這篇關于thinkphp6使用mysql悲觀鎖解決商品超賣問題的實現的文章就介紹到這了,更多相關thinkphp6 商品超賣內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/W07028057/article/details/121455332

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲成人一区二区三区 | 日本激情视频 | 国产欧美日韩综合精品一区二区 | 国产一区二区三区免费 | 亚色图| 欧美日韩综合一区 | 久久国产精品99国产精 | 中文字幕一区二区在线观看 | 国语av在线| 亚洲精品在线视频 | 亚洲精品www久久久久久广东 | av免费资源 | 亚洲视频 中文字幕 | 午夜午夜精品一区二区三区文 | 亚洲视频观看 | 精品国产乱码久久久久久久软件 | 欧美日韩福利 | 婷婷久久五月 | 日本一区二区中文字幕 | 成人免费毛片嘿嘿连载视频 | 中文字幕一区二区在线观看 | 国产成人在线一区 | 日韩中文一区二区三区 | 国产成人精品一区二区在线 | 中文字幕高清免费日韩视频在线 | 日韩精品极品视频在线观看免费 | 黄久久久 | а√天堂中文在线资源8 | 亚洲国产一区二区三区 | 国产综合亚洲精品一区二 | 亚洲国产精品久久久 | 国产精品免费看 | 成人a级片在线观看 | 国产福利在线播放 | theporn国产在线精品 | 好吊妞国产欧美日韩免费观看视频 | 久久夜色精品国产 | 日韩一区二区三区在线观看 | www.久久99| 一区二区三区在线免费播放 | 国产精品九九九 |