1. 程式人生 > >mysql 針對高併發下,同時修改單條資料發生衝突導致資料錯誤的問題(例如:高併發下單,導致庫存為負數)

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 進行鎖定

  這個時候其他使用者是無法查詢到的。

這是目前理解的兩種方法,不過不明白這裡面的具體效能問題是怎麼樣的。也不清楚哪個方案更好。

在這裡 也不講述樂觀鎖和悲觀鎖了   因為本人也並不是完全理解 待我去尋摸一本書,弄明白了 在補充