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

MySQL 樂觀鎖深度解析:版本號、時間戳、MVCC 實現與選型建議

     編輯:MySQL 綜合教學

MySQL 樂觀鎖深度解析

一、樂觀鎖 vs 悲觀鎖:核心理念對比

維度悲觀鎖樂觀鎖
假設前提衝突概率高,先鎖後改衝突概率低,改完再檢查
鎖定時機讀取/修改前加鎖提交更新時檢查版本
並發性能低(長時間持有鎖)高(無鎖讀取,僅提交瞬間檢查)
典型場景庫存扣減、金融轉賬多讀少寫、版本控制系統(SVN/Git)
衝突處理阻塞等待拋出異常,應用層重試
樂觀鎖其實不是「鎖」,而是衝突檢測機制;悲觀鎖才是真正的「避免衝突」機制。

二、兩種主流實現方式

1. 版本號機制(最常用)

  • 表新增 version INT DEFAULT 0 欄位
  • 讀取時帶出 version
  • 更新時:UPDATE t SET col=val, version=version+1 WHERE id=? AND version=old_version
  • affected_rows = 0 表示版本已變,發生衝突

2. 時間戳機制

  • 表新增 ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
  • 邏輯同版本號,比對 ts 值
  • 注意:高併發下毫秒級時間戳可能重複,建議用 DATETIME(6) 或版本號

三、版本控制系統(SVN/Git)視角的直觀類比

  • 樂觀鎖:小張、小李同時編輯同一文件,先提交者成功,後提交者收到衝突提示,需手動合併
  • 悲觀鎖:小張 checkout 鎖定文件,小李必須等待小張 commit 釋放鎖才能編輯

四、選型建議:何時用樂觀,何時用悲觀?

條件推薦策略
併發訪問頻率低、衝突後果輕微(僅需重試)樂觀鎖
併發高、衝突嚴重(如金額錯賬)、需強一致性悲觀鎖(SELECT ... FOR UPDATE)
業務允許「先提交者勝出」,後續人工介入合併樂觀鎖
局限性提醒: 樂觀鎖只能在提交瞬間發現衝突,若業務對「發現過晚」極度敏感(如秒殺超賣),需結合 Lua 腳本 / Redis 分布式鎖 / 數據庫悲觀鎖 多層防護。

五、InnoDB MVCC 多版本並發控制 — 底層實現原理

核心結構:每行隱藏兩個列

  • DB_TRX_ID:創建該行的事務 ID
  • DB_ROLL_PTR:指向 Undo Log 的回滾指鏈

可重複讀(RR)隔離級別下的行可見性判斷

SELECT 時讀取:創建版本 ≤ 當前事務版本 且 (刪除版本為空 OR 刪除版本 > 當前事務版本)
INSERT:保存當前事務版本為創建版本
DELETE:保存當前事務版本為刪除版本
UPDATE:插入新行(創建版本=當前),舊行標記刪除版本=當前

快照讀 vs 當前讀

類型語句示例加鎖行為讀取版本
快照讀SELECT * FROM t WHERE ...不加鎖歷史可見版本
當前讀SELECT ... LOCK IN SHARE MODES 鎖(共享鎖)最新版本
當前讀SELECT ... FOR UPDATEX 鎖(排他鎖)最新版本
當前讀INSERT / UPDATE / DELETEX 鎖最新版本
MVCC 讓「讀不阻塞寫,寫不阻塞讀」成為可能,是 InnoDB 高並發的核心基石。

六、總結

樂觀鎖通過 版本號 或 時間戳 實現無鎖並發,適合讀多寫少場景;InnoDB MVCC 更在引擎層實現了無鎖快照讀,配合 RR 隔離級別解決不可重複讀,但仍存幻讀風險(需 Serializable 或 Gap Lock 解決)。實際架構中,建議:應用層樂觀鎖 + 數據庫 MVCC + 關鍵業務悲觀鎖 三層防護,兼顧效能與一致性。

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