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

MySQL InnoDB 鎖機制實驗:主鍵、索引如何決定行鎖與表鎖

     編輯:MySQL 綜合教學

MySQL InnoDB 鎖機制實驗:主鍵、索引如何決定行鎖與表鎖

在 MySQL 5.5.20 上通過雙 Session 並發實驗,驗證 InnoDB 在不同表結構(無主鍵、有主鍵、無索引、有索引)下的鎖行為,結論:命中索引(含主鍵)才是行鎖,否則退化為表鎖。

實驗環境

CREATE TABLE test (a INT(5), b VARCHAR(10), c VARCHAR(10));
INSERT INTO test VALUES (1,'111','111'),(2,'222','222'),(3,'333','333'),
                        (4,'444','444'),(5,'555','555'),(6,'666','666');
SET AUTOCOMMIT=0;

場景與結果總表

場景Session 1Session 2結果
無主鍵,更新不同行 (a=1 vs a=2)UPDATE ... WHERE a=1UPDATE ... WHERE a=2表鎖:S2 等待超時
無主鍵,INSERT + 更新不同行INSERT (7,'777','777')UPDATE ... WHERE a=2表鎖:S2 等待超時
加主鍵 (PK=a),更新不同行UPDATE ... WHERE a=1UPDATE ... WHERE a=2行鎖:並發成功
有主鍵,更新同一行UPDATE ... WHERE a=1UPDATE ... WHERE a=1行鎖:S2 等待(正常行鎖競爭)
有主鍵,INSERT + 更新不同行INSERT (8,'888','888')UPDATE ... WHERE a=1行鎖:並發成功
無索引,更新非索引列不同值 (b='111' vs '222')UPDATE ... WHERE b='111'UPDATE ... WHERE b='222'表鎖:S2 等待超時
建索引 (IND=b),更新不同值UPDATE ... WHERE b='111'UPDATE ... WHERE b='222'行鎖:並發成功

核心結論

  1. 主鍵 = 聚簇索引,Where 條件命中主鍵 → 行鎖。
  2. 二級索引命中 → 行鎖(先鎖二級索引記錄,再鎖聚簇索引記錄)。
  3. 全表掃描(無索引可用) → 表鎖(實為鎖所有記錄 + 間隙鎖),併發度極低。
  4. 與 Oracle「預設行鎖、無索引也行鎖」不同,InnoDB 強依賴索引 實現行級鎖。

實戰建議

  • 所有表必須有主鍵(建議自增 BIGINT)。
  • WHERE/JOIN/ORDER BY 涉及的欄位建立適當索引。
  • 避免大範圍更新/刪除未命中索引的 SQL,必要時強制索引或重寫。
  • 使用 EXPLAIN 確認 type=ref/eq_ref 而非 ALL。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved