Mysq詳細(xì)講解如何解決庫存并發(fā)問題
面臨的問題
長話短說,假設(shè)我們現(xiàn)在面臨以下需求
- 商品的庫存有兩千,賣完為止
- 某商品本日的售賣只允許賣出一百,賣完為止
如何實現(xiàn)
我提出的方案也很簡單,使用樂觀鎖的方式。
以下是具體的方案
-- stock: 當(dāng)前庫存數(shù) number:扣減的數(shù)量 -- UPDATE t SET stock -= number WHERE stock >= number
外加上事務(wù),便可以實現(xiàn)一個基本的庫存扣減操作。大部分情況下,無需擔(dān)心所謂的“并發(fā)問題”。事務(wù)具有的特性,會在此處幫你解決的掉這個大難題。
(簡單的說:事務(wù)會在執(zhí)行 非查詢 的操作的時候,會實現(xiàn)類似鎖的功能。直到前面的事物提交或者回滾之前,后續(xù)的操作都會被掛?。?/p>
需求具體實現(xiàn)的方案
1.商品的庫存兩千,賣完為止
其實從理論上,想解決這個問題,只依靠上文之中的update語句便可以完成。
具體步驟如下:
- 執(zhí)行UPDATE 語句,查看其結(jié)果 。
- 若是,則執(zhí)行后續(xù)操作
- 若否,代碼回滾
具體代碼如下
//開始事務(wù)
beginTransaction();
// 扣減庫存前的業(yè)務(wù)
// 執(zhí)行扣減庫存操作
boolean reduceStockSuccess = reduceStock();
if(!reduceStockSuccess){
//扣減庫存失敗,代碼回滾
rollback();
return;
}
// 執(zhí)行扣減庫存后的業(yè)務(wù)操作
//記錄庫存
writeRecod();
//提交事務(wù)
commit();
return;
雖然,程序其實如此便可。但是從個人的角度去看,我還是建議大家多做一點校驗,以減少UPDATE程序運行次數(shù)。
就比如說,我們可以在前面加一個查詢當(dāng)前庫存數(shù)量代碼。
主要的目的在于,雖然這個校驗代碼,不能說百分百的解決問題 ,擋住所有的流量。但是卻可以擋住大部分無意義的流量,調(diào)用UPDATE的次數(shù)。
簡單來說,就跟我們小時候玩坦克大戰(zhàn)一樣,雖然我們玩家不能擋住所有的進攻者。但也并不是隨隨便便誰都可以往我們家基地開炮。
//開始事務(wù)
beginTransaction();
// 扣減庫存前的業(yè)務(wù)
int stock = getStock();
if(stock <= 0 ){
//庫存不足,退出程序
rollback();
return;
}
// 執(zhí)行扣減庫存操作
boolean reduceStockSuccess = reduceStock();
if(!reduceStockSuccess){
//扣減庫存失敗,代碼回滾
rollback();
return;
}
// 執(zhí)行扣減庫存后的業(yè)務(wù)操作
//記錄庫存
writeRecod();
//提交事務(wù)
commit();
return;
2 . 日庫存數(shù)一百 , 賣完為止
該需求相比1來說,問題在于。單從庫存表,記錄表來說。除非我們在新增到記錄表的SQL里面將每日庫存數(shù)100接入。否則,我們無法通過事務(wù)與SQL來幫我們解決并發(fā)問題。
但是我們又不可能在記錄購買信息的代碼內(nèi),每日庫存數(shù)100的邏輯耦合進去。
因此,這個問題對于MYSQL來說是個死局。
若想單靠MYSQL之力若想破局,我們只能依靠將每日庫存數(shù)的這個邏輯,專門設(shè)計一張數(shù)據(jù)表。
如設(shè)計一張商品每日購買數(shù)量記錄表記錄某個商品每日被購買的數(shù)量。
在每次購買的時候都更新一下本日購買的數(shù)量
UPDATE day_t SET day_stock += number WHERE day_stock + number <= 100
雖然能解決需求問題,但是表現(xiàn)出來的問題依然是業(yè)務(wù)耦合進公關(guān)表內(nèi)。
- 每日購買數(shù)量表,不應(yīng)當(dāng)僅僅為每日購買上限服務(wù)。當(dāng)前的解決問題的方案,等同于解決問題的同時又制造了一個差不多的問題。只是一個問題轉(zhuǎn)移到了其他部分出問題
- 即使我們?yōu)樵撔枨髮iT創(chuàng)建一張表,但是隨著后續(xù)的數(shù)據(jù)表越來越多,程序的管理性卻越來越差,比如后續(xù)還會出現(xiàn)周限制,月限制,年限制等等等等。
總結(jié)
現(xiàn)在我們可以看出,使用MYSQL的方式雖然簡單,但是卻有著非常大的局限性。
但這里也并不是說某些方案一定好,卻也一定差。
主要看當(dāng)前的業(yè)務(wù),MYSQL的方式,適用于最底層。適合完成某個業(yè)務(wù)最原始的功能。
到此這篇關(guān)于Mysq詳細(xì)講解如何解決庫存并發(fā)問題的文章就介紹到這了,更多相關(guān)Mysq庫存并發(fā)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SQL NULL值的定義測試處理空數(shù)據(jù)及SQL?UPDATE語句使用詳解
這篇文章主要為大家介紹了SQL NULL值的定義測試處理空數(shù)據(jù)及SQL?UPDATE語句使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-11-11
MySql 錯誤Incorrect string value for column
能使用中文進行搜索,但是insert into 中文是可以的。我的數(shù)據(jù)庫和數(shù)據(jù)表中所有的charset都是設(shè)置的utf8。2010-12-12
淺談MySQL數(shù)據(jù)同步到 Redis 緩存的幾種方法
本文主要介紹了淺談MySQL數(shù)據(jù)同步到 Redis 緩存的幾種方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03
centos上安裝mysql并設(shè)置遠(yuǎn)程訪問的操作方法
這篇文章主要介紹了centos上安裝mysql并設(shè)置遠(yuǎn)程訪問的操作方法,需要的朋友可以參考下2017-11-11
mysql 添加用戶并分配select權(quán)限的實現(xiàn)

