首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 事務鎖實戰:SELECT ... FOR UPDATE 實現庫存扣減防超賣

     編輯:MySQL 資料庫相關知識

高併發秒殺場景下,庫存扣減必須保證「查詢-判斷-更新」原子性。SELECT ... FOR UPDATE 在事務中鎖定目標行,阻塞其他事務讀寫,是防超賣的核心手法。

標準防超賣模板

START TRANSACTION;

-- 1. 鎖定庫存行 (排他鎖,阻塞其他 FOR UPDATE / UPDATE / DELETE)
SELECT stock FROM goods WHERE id = 1 FOR UPDATE;

-- 2. 應用層判斷
IF stock > 0 THEN
  -- 3. 扣減
  UPDATE goods SET stock = stock - 1 WHERE id = 1;
  COMMIT;
ELSE
  ROLLBACK;
  -- 返回「售罄」
END IF;

關鍵機制解析

操作鎖類型相容性
SELECT ... FOR UPDATEX 鎖 (排他)阻塞其他 X 鎖、S 鎖 (LOCK IN SHARE MODE)
SELECT ... LOCK IN SHARE MODES 鎖 (共享)相容 S 鎖,阻塞 X 鎖
普通 SELECT無鎖 (MVCC 快照讀)不阻塞,讀到舊版本

避坑指南

  • 必須在事務中使用:自動提交模式下 FOR UPDATE 鎖即釋放,失去保護作用。
  • 索引命中:WHERE 條件必須走索引 (主鍵/唯一/普通),否則升級為表鎖,並發度歸零。
  • 死鎖預防:多表更新時統一加鎖順序 (如按 ID 升序);捕獲 ERROR 1213 (Deadlock) 重試。
  • 鎖等待超時:innodb_lock_wait_timeout 預設 50s,高併發建議降低至 5-10s 快速失敗。

進階:樂觀鎖替代方案

UPDATE goods SET stock = stock - 1, version = version + 1 
WHERE id = 1 AND stock > 0 AND version = @old_version;
-- affected_rows = 1 成功,0 失敗重試

樂觀鎖無鎖開銷,適合衝突率低場景;悲觀鎖 (FOR UPDATE) 適合衝突率高、強一致性場景 (如扣款、庫存)。

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