mysql 針對高併發下,同時修改單條資料發生衝突導致資料錯誤的問題(例如:高併發下單,導致庫存為負數)
畢業後第一次做的專案就是電商,但是當時也不明白這個問題。
所以給自己埋下一個坑。
先說說當初的做法,和遇到的問題。
//開啟事務
start transaction;
//查詢庫存
select number from item where id = 1;
//如果大於購買數量進入購買,如果小於返回錯誤 並rollback
//進入購買
update item set item number = number - 1 where id = 1;
//如果成功commit 如果失敗 rollback
問題:
當兩個人 同時下單,同時進入事務 這個時候兩個人查的數量是相同的,以下為模擬
步驟1=》使用者1:查詢item 數量為5
步驟2=》使用者2:查詢item 數量為5
步驟3=》使用者1:買了五個將item的數量減5 並且成功
步驟4=》使用者2:買了五個將item的數量減5 由於mysql的自身鎖的問題 (因為使用者1 沒有提交 所以使用者2 需要等待使用者1 commit 才能真正的修改成功)
步驟5=》使用者1:commit 成功修改數量並且成功購買
步驟6=》使用者2:等待狀態解除,將item的數量也成功減5 數量變為-5
錯誤:最後item為-5
解決的辦法:
1.樂觀鎖:在每個使用者commit 之前再重新查詢 item的數量 如果為負數 rollback 並且說明庫存不足
2.悲觀鎖:在查詢的時候 select * from item where id = 1 改為 select * from item where id = 1 for update 進行鎖定
這個時候其他使用者是無法查詢到的。
這是目前理解的兩種方法,不過不明白這裡面的具體效能問題是怎麼樣的。也不清楚哪個方案更好。
在這裡 也不講述樂觀鎖和悲觀鎖了 因為本人也並不是完全理解 待我去尋摸一本書,弄明白了 在補充