1 基礎
在電商系統中扣減庫存是一步非常關鍵的操作,例如秒殺系統中一定要防止超賣情況出現,如果商家設定了100件庫存但是最後賣出1000件,這樣就會產生資金損失。在扣減庫存時一般使用如下語句:
udpate goods set stock = stock - #{acquire} where sku_id = #{skuId} and stock - #{acquire} >= 0
讓我們分析這句話如何有效防止庫存超售,以便保護庫存資源。在本文的示範中,我們採用MySQL Innodb引擎,隔離等級設為可重複讀取。
1.1 共享鎖定與排它鎖
共享鎖定(share Lock)又稱為讀鎖,實現共享鎖定語句如下:
select lock in share mode
排它鎖(exclusive Lock)又被稱為寫鎖,實現排它鎖語句如下:
select for update update delete insert
共享鎖與排它鎖相容關係如下表:
我們透過實例分析上述相容關係,先建立測試表並寫入測試資料:
CREATE TABLE `test_account` ( `id` bigint(20) NOT NULL, `name` varchar(20) DEFAULT NULL, `account` bigint(20) DEFAULT NULL, `version` bigint(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into `test_account`(`id`,`name`,`account`,`version`) values (1,'A',100,1); insert into `test_account`(`id`,`name`,`account`,`version`) values (2,'B',200,1); insert into `test_account`(`id`,`name`,`account`,`version`) values (3,'C',300,1);
(1) 讀讀相容
共用鎖定與共用鎖定之間相容,在如下實例中session1在t3時刻,session2在t4時刻執行查詢均可以取得預期結果:
(2) 讀寫互斥
共享鎖定與排它鎖之間互斥,在如下實例中session1在t3時刻加上共享鎖,可以正確讀取結果,但是session2在t4時刻嘗試加排它鎖,但是此時鎖被session1佔有,session2需要等待,當session1長時間不釋放鎖定時,session2拋出鎖定逾時異常:
(3) 寫寫互斥
排它鎖與排它鎖之間互斥,在如下實例中session1在t3時刻加排它鎖,可以正確讀取結果,但是session2在t4時刻嘗試加排它鎖,但是此時鎖被session1佔有,session2需要等待,當session1長時間不釋放鎖時,session2拋出鎖定超時異常:
1.2 目前讀與快照讀取
MySQL Innodb儲存引擎實作基於多版本並發控制協定MVCC,在MVCC並發控制中讀取操作可以分成快照讀取與目前讀取。
快照讀取不需要加鎖,讀取的是記錄可見版本,有可能是歷史版本。類比訂單快照,即使用戶下單後商品價格變化,訂單快照仍保持不變。實作目前讀語句如下:
select
為了讀取最新版本的記錄時不被其它事務修改,需要對目前記錄進行加鎖。實作目前讀語句如下:
select lock in share mode select for update update delete insert
我們透過一個實例分析快照讀和目前讀,session2在t4時刻修改記錄並在t5時刻提交,session1在t6時刻進行了快照讀,讀取的是本事務開始時結果100,在t7時刻進行了當前讀,讀取的是記錄最新版本結果101:
當前讀流程是怎麼樣的呢?我們以update為例進行分析目前讀取流程:
第一次程式實例發出目前讀取請求,儲存引擎傳回符合where條件的第一筆記錄並加鎖,程式實例再發出更新請求,儲存引起操作完成回應成功。依序執行直到所有滿足where條件記錄執行完成為止。
這裡我們做一些引申,RR層級提供了兩種機制避免幻讀問題:第一種方式是快照讀,讀取的是目前事務開啟時的快照。一種針對目前讀取的方法是使用Next-Key Lock機制來防止幻讀。
2 樂觀鎖定原理
我們透過一個問題將上述知識整合起來:有兩個執行緒在同一時刻執行如下語句,請問id=1這條記錄account值會不會成功扣減兩次?
update test_account set account = account - 100, version = version + 1 where id = 1 and version = 1
上述語句使用了樂觀鎖,我們知道樂觀鎖就是對資源進行保護的,所以答案是不會扣減兩次,但是不能就此止步,需要結合第一章節知識進行進一步分析:
t2時刻session1和session2同時執行update操作,由於update會加排它鎖,所以兩者只能有一個成功:session1成功,session2阻塞等待排它鎖釋放。
t3時刻session1提交事務釋放排它鎖,此時session2獲取到鎖進行當前讀,但是此時id=1記錄version值已經變成了2,執行語句已經查詢不到待更新數據,所以沒有記錄發生更新。
3 扣減庫存原理
如果理解了第二章節樂觀鎖原理,那麼扣減庫存原理已經顯而易見,我們假設商品只剩下1件庫存,如果兩個線程同時執行扣減庫存,會發生超賣的情況嗎?
t2時刻session1和session2同時執行updatek扣減庫存,由於update會加排它鎖,所以兩者只能有一個成功:session1成功,session2阻塞等待排它鎖釋放。
t3時刻session1提交事務釋放排它鎖,此時session2獲取到鎖進行當前讀,但是此時商品1庫存已經變為0,已經不滿足(where stock - 1 >= 0)條件,執行語句已經查詢不到待更新數據,所以沒有記錄發生更新。
以上是MySQL中樂觀鎖扣減庫存原理是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

掌握添加MySQL用戶的方法對於數據庫管理員和開發者至關重要,因為它確保數據庫的安全性和訪問控制。 1)使用CREATEUSER命令創建新用戶,2)通過GRANT命令分配權限,3)使用FLUSHPRIVILEGES確保權限生效,4)定期審計和清理用戶賬戶以維護性能和安全。

chosecharforfixed-lengthdata,varcharforvariable-lengthdata,andtextforlargetextfield.1)chariseffity forconsistent-lengthdatalikecodes.2)varcharsuitsvariable-lengthdatalikenames,ballancingflexibilitibility andperformance.3)

在MySQL中處理字符串數據類型和索引的最佳實踐包括:1)選擇合適的字符串類型,如CHAR用於固定長度,VARCHAR用於可變長度,TEXT用於大文本;2)謹慎索引,避免過度索引,針對常用查詢創建索引;3)使用前綴索引和全文索引優化長字符串搜索;4)定期監控和優化索引,保持索引小巧高效。通過這些方法,可以在讀取和寫入性能之間取得平衡,提升數據庫效率。

ToaddauserremotelytoMySQL,followthesesteps:1)ConnecttoMySQLasroot,2)Createanewuserwithremoteaccess,3)Grantnecessaryprivileges,and4)Flushprivileges.BecautiousofsecurityrisksbylimitingprivilegesandaccesstospecificIPs,ensuringstrongpasswords,andmonitori

tostorestringsefliceflicyInmySql,ChooSetherightDataTypeBasedyOrneOrneEds:1)USEcharforFixed-LengthStstringStringStringSlikeCountryCodes.2)UseVarcharforvariable-lengtthslikenames.3)USETEXTCONTENT.3)

選擇MySQL的BLOB和TEXT數據類型時,BLOB適合存儲二進制數據,TEXT適合存儲文本數據。 1)BLOB適用於圖片、音頻等二進制數據,2)TEXT適用於文章、評論等文本數據,選擇時需考慮數據性質和性能優化。

No,youshouldnotusetherootuserinMySQLforyourproduct.Instead,createspecificuserswithlimitedprivilegestoenhancesecurityandperformance:1)Createanewuserwithastrongpassword,2)Grantonlynecessarypermissionstothisuser,3)Regularlyreviewandupdateuserpermissions

mySqlStringDatatAtatPessHouldBechoseBasedondatActarActeristicsAndusecases:1)USEcharforFixed lengthStstringStringStringSlikeCountryCodes.2)usevarcharforvariable-lengtthslikeLikenames.3)usebarnionororvarinyorvarinyorvarybinarydatalgebenedaTalgeextocrabextrapon.4)


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

WebStorm Mac版
好用的JavaScript開發工具

SublimeText3漢化版
中文版,非常好用

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具