一、 索引篇:B+樹、最左前綴與失效場景
Q1:MySQL 為什麼使用 B+ 樹而不是 B 樹或哈希表做索引?
- 標準答案:
- B+ 樹 vs B 樹: B+ 樹的非葉子節點只存索引鍵,不存數據,因此單個頁能存放更多鍵,樹的高度更低,I/O 次數更少。所有數據都在葉子節點,且葉子節點用鏈表連接,範圍查詢效率極高。
- B+ 樹 vs 哈希表: 哈希表只支持等值查詢(
=),不支持範圍查詢(>,<,BETWEEN)和排序(ORDER BY),且哈希衝突會影響性能。B+ 樹則完美支持這些操作。
- 加分項:
“MyISAM 引擎也用 B+ 樹,但 InnoDB 的聚簇索引將數據和主鍵索引存在一起,進一步減少了回表查詢的 I/O。”
Q2:什麼是最左前綴原則?哪些情況會導致索引失效?
- 標準答案:
- 最左前綴原則: 對於聯合索引
(a, b, c),查詢條件必須從最左邊的列開始,並且不能跳過中間列。有效查詢:WHERE a=1、WHERE a=1 AND b=2、WHERE a=1 AND b=2 AND c=3。無效查詢:WHERE b=2、WHERE a=1 AND c=3(跳過 b)。 - 索引失效常見場景:
- 對字段進行函數操作或計算:
WHERE YEAR(create_time) = 2023 - 類型隱式轉換: 字符串字段用數字查詢
WHERE phone = 13800138000(phone 是 varchar) - 使用
!=或<> LIKE以通配符開頭:WHERE name LIKE '%張'OR條件中部分字段無索引
- 實戰建議:
“可以用
EXPLAIN命令查看執行計劃,重點關注type(最好為ref或range)、key(是否命中索引)、Extra(避免出現Using filesort或Using temporary)。”
二、 事務與鎖:ACID、隔離級別與死鎖
Q3:請解釋事務的 ACID 特性,並説明 MySQL 如何實現?
- 標準答案:
- A (Atomicity) 原子性: 通過 Undo Log 實現。事務失敗時,根據 Undo Log 回滾已執行的操作。
- C (Consistency) 一致性: 由 A、I、D 共同保證,數據庫從一個一致狀態轉移到另一個一致狀態。
- I (Isolation) 隔離性: 通過 鎖機制 + MVCC(多版本併發控制) 實現。不同隔離級別提供不同程度的併發控制。
- D (Durability) 持久性: 通過 Redo Log 實現。事務提交時,先寫 Redo Log 到磁盤,再異步刷髒頁到數據文件,確保崩潰後可恢復。
Q4:MySQL 的四種隔離級別是什麼?分別解決了哪些問題?
|
隔離級別 |
髒讀 |
不可重複讀 |
幻讀 |
InnoDB 默認 |
|
READ UNCOMMITTED |
✅ |
✅ |
✅ |
❌ |
|
READ COMMITTED (RC) |
❌ |
✅ |
✅ |
❌ |
|
REPEATABLE READ (RR) |
❌ |
❌ |
⚠️(基本解決) |
✅ |
|
SERIALIZABLE |
❌ |
❌ |
❌ |
❌ |
- 關鍵點:
- 髒讀: 讀到未提交的數據。
- 不可重複讀: 同一事務內,兩次讀取同一行數據結果不同(被 UPDATE)。
- 幻讀: 同一事務內,兩次查詢返回的行數不同(被 INSERT/DELETE)。
- InnoDB 的 RR 級別通過 MVCC + 間隙鎖(Gap Lock)解決了幻讀問題。
Q5:什麼是死鎖?如何排查和避免?
- 標準答案:
- 死鎖: 兩個或多個事務互相持有對方需要的鎖,形成循環等待。
- 排查: 使用
SHOW ENGINE INNODB STATUS查看最近的死鎖日誌。 - 避免:
- 按固定順序訪問表和行。
- 減少事務粒度,儘快提交。
- 為表添加合理的索引,避免全表掃描加鎖。