一、 索引篇: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=1WHERE a=1 AND b=2WHERE a=1 AND b=2 AND c=3。無效查詢:WHERE b=2WHERE a=1 AND c=3(跳過 b)。
  • 索引失效常見場景:
  1. 對字段進行函數操作或計算: WHERE YEAR(create_time) = 2023
  2. 類型隱式轉換: 字符串字段用數字查詢 WHERE phone = 13800138000(phone 是 varchar)
  3. 使用 != 或 <>
  4. LIKE 以通配符開頭: WHERE name LIKE '%張'
  5. OR 條件中部分字段無索引
  • 實戰建議:

“可以用 EXPLAIN 命令查看執行計劃,重點關注 type(最好為 refrange)、key(是否命中索引)、Extra(避免出現 Using filesortUsing 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 查看最近的死鎖日誌。
  • 避免:
  1. 按固定順序訪問表和行。
  2. 減少事務粒度,儘快提交。
  3. 為表添加合理的索引,避免全表掃描加鎖。