一、腦圖:鎖全景(先記結構,再填細節)
鎖層級
├─ 表鎖
│ ├─ 意向鎖 IS / IX
│ └─ 表鎖 READ / WRITE
└─ 行鎖├─ 記錄鎖 Record├─ 間隙鎖 Gap└─ 臨鍵鎖 Next-Key
二、15 問 15 答(面試官一問一答節奏)
# | 高頻問題 | 15 秒答案 |
---|---|---|
1 | 行鎖 vs 表鎖 | 行鎖鎖“行”,表鎖鎖“整表”;InnoDB 默認行鎖,MyISAM 只有表鎖。 |
2 | 何時加表鎖 | ① LOCK TABLES 顯式加;② ALTER/TRUNCATE 隱式加;③ UPDATE 無索引退化為全表鎖。 |
3 | 怎么避免表鎖 | ① 用 InnoDB;② 條件列建索引;③ 避免全表掃描;④ 分批更新。 |
4 | 樂觀鎖 | 用“版本號”或“CAS”替代數據庫鎖;MySQL 實現:UPDATE t SET val=new, ver=ver+1 WHERE id=? AND ver=? ;影響行數=1 即成功,0 則重試。 |
5 | 意向鎖 | 表級“信號燈”,IS 表示要加行級共享鎖,IX 表示要加行級排他鎖;例:事務 A 先在 user 表加 IX,再在 id=10 行加 X。 |
6 | 共享鎖 S vs 排他鎖 X | S:讀共享,多個事務可同時持有;X:寫獨占,任何其他鎖互斥。 |
7 | 兩階段加鎖 | 擴展階段只加鎖,收縮階段只放鎖;InnoDB RR 默認強 2PL(所有鎖事務結束才放)。 |
8 | 記錄鎖 | 鎖一行索引記錄;例:SELECT * FROM t WHERE id=1 FOR UPDATE (唯一索引且命中)。 |
9 | 間隙鎖 | 鎖兩個索引記錄之間的“空隙”,防插入;例:SELECT * FROM t WHERE id=15 FOR UPDATE (id=15 不存在)。 |
10 | 臨鍵鎖 | 記錄鎖 + 間隙鎖,左開右閉;RR 默認加;范圍查詢:id BETWEEN 10 AND 20 → (10,20]。 |
11 | RC 有 GAP/Next-Key? | 沒有,RC 只有記錄鎖(除非顯式 FOR UPDATE 且用到外鍵或唯一檢查)。 |
12 | RR 如何防幻讀 | MVCC(快照讀)+ 臨鍵鎖(當前讀)雙管齊下。 |
13 | 何時加臨鍵鎖 | RR 下:① 范圍查詢;② 非唯一索引等值查詢;③ UPDATE/DELETE 無 LIMIT。 |
14 | 唯一索引 vs 普通索引 | 唯一索引等值命中→記錄鎖;普通索引等值→臨鍵鎖;唯一索引插入需額外 S 鎖做唯一檢查。 |
15 | 死鎖案例 | 線上轉賬批量更新賬戶表,順序相反 → 交叉死鎖;排查:SHOW ENGINE INNODB STATUS ;解決:統一按主鍵升序排序 + 批量單 SQL 更新;監控:Prometheus 死鎖告警。 |
三、3 個口訣(背口訣,不背細節)
-
鎖種類
“記錄鎖鎖點,間隙鎖鎖縫,臨鍵鎖鎖點縫”。 -
RR 防幻讀
“MVCC 看舊照,臨鍵鎖堵新插”。 -
避免死鎖
“順序加鎖、批量合并、索引覆蓋”。
四、面試官追問彩蛋
Q:UPDATE t SET c1=1 WHERE c2=2
無索引會怎樣?
A:全表掃描 → 每條記錄加 X 鎖 + 所有間隙加 Gap 鎖 → 等價鎖全表;解決:給 c2 建聯合索引或改為 id IN (SELECT id ...)
。