首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 行鎖 FOR UPDATE 實現庫存扣減防超賣:事務+SELECT FOR UPDATE 實戰模式

     編輯:MySQL 綜合教學

業務場景

電商大促:庫存 1 件,用戶 A、B 同時下單。必須保證只有一單成功,不超賣、不少賣。

核心模式

  查詢方式鎖類型並發行為
  
    SELECT ...無鎖(MVCC 快照讀)A、B 同時讀到 stock=1,皆通過判斷 → 超賣
    SELECT ... LOCK IN SHARE MODE共享鎖 (S)A、B 可共存,但 UPDATE 需等 S 鎖釋放 → 仍可能超賣
    SELECT ... FOR UPDATE排他鎖 (X)A 先得鎖,B 阻塞等待 → A 提交後 B 讀到 stock=0 → 正確
  


關鍵細節

  1. 必須在事務中:自動提交模式下 FOR UPDATE 鎖即得即釋,無保護效果
  2. 走索引:WHERE id = 1 命中主鍵,鎖定單行;無索引會升級為表鎖/間隙鎖,嚴重降低並發
  3. 業務判斷在應用層:資料庫只負責鎖與扣減,邏輯判斷放應用代碼
  4. 超時控制:innodb_lock_wait_timeout=50(預設 50s),超時自動回滾
  5. 死鎖預防:多表更新時統一按主鍵遞增順序加鎖

進階:樂觀鎖替代方案(低並發/重試成本低)

  方案並發能力實現複雜度適用場景
  
    SELECT FOR UPDATE (悲觀鎖)高(毫秒級持鎖)低庫存扣減、座位鎖定、強一致性
    樂觀鎖 (version)極高(無鎖)中衝突率低、可重試、高吞吐
    Redis Lua 原子扣減極高(單執行緒)中極高並發、最終一致可接受
  


小結

事務 + SELECT ... FOR UPDATE + 應用層判斷 + UPDATE 是 MySQL 防超賣的經典模式。關鍵三點:**在事務中、走主鍵索引、鎖住再判斷**。高併發可升級 Redis Lua 或樂觀鎖,但邏輯更複雜。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved