1. 程式人生 > 實用技巧 >MySQL面試總結

MySQL面試總結

常見問題如下

  1. InnoDB和MyISAM的差異
  2. MySQL邏輯架構 [Tencent微視]
  3. Select語句的執行過程
  4. 事務的基本特性
  5. MySQL的隔離級別分別解決了什麼問題
  6. MVCC
  7. NextKey
  8. MySQL有那些鎖
  9. redolog/undolog/binlog
  10. 聚簇索引/二級索引
  11. 索引覆蓋/回表
  12. 索引的資料結構
  13. 索引失效
  14. explain命令

答案

MySQL邏輯架構

第一層與傳統C/S 架構相似,包含:連線處理、授權認證、安全等。

第二層是MySQL的核心服務 包括:查詢解析、分析、優化、快取以及所有的內建函式(例如:日期、時間、數學和加密函式)。以及所有的跨儲存引擎的功能:儲存過程、觸發器、檢視等。

第三層是儲存引擎。儲存引擎負責MySQL中資料的儲存和提取。伺服器通過API和儲存引擎進行通訊。
不同的儲存引擎對外暴露統一封裝好的API提供呼叫,呼叫者不需要關注底層實現,不同儲存引擎之間也不會相互通訊,而只是簡單的響應上層的伺服器請求。

InnoDB和MyISAM的差異

  1. 事務 InnoDB支援,MyISAM不支援。
  2. 外來鍵 InnoDB支援,而MyISAM不支援。
  3. 索引B+葉子階段儲存的資訊不一樣,InnoDB是聚簇索引葉子節點儲存的是資料檔案,輔助索引的葉子節點是主鍵的值;而MyISAM的B+樹主鍵索引和輔助索引的葉子節點都是資料檔案的地址指標。
  4. InnoDB不儲存表的具體行數,執行select count(*) 需要全表掃描。而MyISAM用一個變數儲存了整個表的行數。[InnoDB 無內建變數是因為不同事務下的行數不一樣]
  5. InnoDB支援表、行(預設)級鎖,而MyISAM支援表級鎖。[InnoDB的行鎖是實現在索引上的,而不是鎖在物理行記錄上,如果訪問沒有命中索引,也無法使用行鎖,將要退化為表鎖。update ... where 沒命中索引會鎖整個表]
  6. InnoDB表必須有唯一索引(如主鍵)(使用者沒有指定的話會自己找/生產一個隱藏列Row_id來充當預設主鍵),而Myisam可以沒有

MyISAM:寫操作是鎖表[排他鎖],讀操作是共享鎖,支援在讀的時候插入資料,讀效能優秀,不支援事務,崩潰後修復困難。

Select語句的執行過程

  1. 客戶端傳送一條查詢給伺服器
  2. 伺服器先查詢快取,如果命中了快取,立刻返回儲存在快取中的結果。否則進入下一階段。
  3. 伺服器進行SQL解析,預處理,染回優化器生產對應的執行計劃。
  4. MySQL 根據優化器生成的對應的執行計劃,呼叫儲存引擎的API來執行查詢。
  5. 將結果返回給客戶端。

事務的基本特性

ACID 原子性/永續性/隔離性/一致性

一致性:一個事務必須使資料庫從一個一致性狀態變換到另一個一致性狀態[語義上的合法狀態],原子性/永續性/隔離性都是為了來保障一致性的。

ACID實現原理

  1. C 一致性:
    • 資料庫層面:資料庫通過A原子性、I隔離性、D永續性來保證一致性。
    • 應用層:通過程式碼保障邏輯上的一致,人為決定是否回滾和提交事務。
  2. A 原子性: 事務要麼成功要麼失敗,不允許部分成功失敗,通過undo log回滾來保障。
  3. D 永續性: 持久是通過redo log
  4. I 隔離性: 鎖+MVCC機制來保障不同事務之間不出現相互影響。

MySQL隔離級別

讀未提交/讀已提交/可重複讀/序列化

MySQL預設是 可重複讀,實際專案中一般使用讀以及提交

  • 在RR隔離級別下,存在間隙鎖,出現死鎖的概率比RC的大。
  • 在RR隔離級別下,列條件沒中索引會鎖表,RC這種情況下鎖行[這個存疑 待考證]。

髒讀/不可重複讀/幻讀

  1. 髒讀:讀出來其他事物還未提交的資料
  2. 不可重複讀:在同一個事務中,針對相同的行,2次查詢的資料內容不一致。
  3. 幻讀: 在同一個事務中的 相同條件的 多次查詢出現了行的增減。

不可重複讀側重的是資料內容的修改,幻讀側重的是資料行的增刪。

redolog/undolog/binlog

Redolog:來記錄某資料塊被修改後的值,可以用來恢復未寫入 datafile 的已成功事務的資料。[事務At提交成功 但未寫入datafile,系統重啟,重啟後會根據redolog執行剩下的更新操作]

Undolog:也就是我們常說的回滾日誌檔案 主要用於事務中執行失敗,進行回滾,以及MVCC中對於資料歷史版本的檢視。

binlog:是記錄所有資料庫表結構變更(例如CREATE、ALTER TABLE…)以及表資料修改(INSERT、UPDATE、DELETE…)的二進位制日誌檔案。

MVCC機制

  • trx_id 記錄最新修改該行的事務號
  • roll_pointer 儲存的是指標指向上一個版本的位置資訊.[指向undoLog,插入操作時無上個版本 該欄位為空]
  • ReadView 用來儲存當前活躍的事務[記錄的是trx_id],也就是開始還未提交的事務。如果當前行的trx_id小於Rv中的最小值,說明事務以提交當前行可展示,若trx_id在RV的範圍內,說明當前行正在進行事務中,不能被展示,則根據roll_point找到上一行的資訊,並且判斷trx_id和RV的關係來辨別是否可以展示,若不可以則重複以上操作。

RC級別下每次查詢都會使用一個最新的ReadView,RR級別下第一次讀會生成一個ReadView,之後的讀都複用之前的ReadView。

MVCC只在RR RC2個級別下工作,Read Uncommit 總是讀取到最新的行而不是符合當前事務版本的資料行,Serializable會對讀取的所有行加鎖,也用不上多版本併發控制.

MySQL的鎖

官方文件上標註的鎖

  1. Shared and Exclusive Locks 共享鎖(S)/排他鎖(X) InnoDB實現的行級鎖定就包含共享鎖和排他鎖
  2. Intention Locks(意向鎖) 意向鎖是表級鎖,指示事務稍後對錶中的行需要哪種型別的鎖(共享鎖或排他鎖)。有兩種型別的意圖鎖:意圖共享鎖(IS)
  3. Record Locks(記錄鎖)
  4. Gap Locks(間隙鎖):間隙鎖可以被多個事務同時鎖定。
  5. Next-Key Locks : 索引記錄上的記錄鎖定和索引記錄之前的間隙上的間隙鎖定的組合。[ record lock + Cap lock 鎖住當前記錄及記錄前後最近的間隙防止其他事務插入資料出現幻讀的現象。]
  6. Insert Intention Locks(插入意向鎖) :如果多個事務未插入間隙中的相同位置,則無需等待彼此插入的多個事務。假設有索引記錄,其值分別為4和7。單獨的事務分別嘗試插入值5和6,在獲得插入行的排他鎖之前,每個事務都使用插入意圖鎖來鎖定4和7之間的間隙,但不要互相阻塞,因為行是無衝突的。
  7. AUTO-INC Locks
  8. Predicate Locks for Spatial Indexes

行鎖: 可以分為共享鎖S和排他鎖X

索引的資料為什麼是B+樹

MySQL查詢效率中有個很關鍵的指標 磁碟IO次數,且磁碟IO一次讀出的資料量是固定的,B-數非葉子節點上比b+數多了資料域data,會使當前IO下的磁碟IO次數增多,且B+數的所有資料都在葉子節點且存在指向下一個葉子節點的指標便於範圍查詢,B-樹的範圍查詢需要遍歷整個樹。

紅黑樹一般是在記憶體中使用的資料結構,若用在資料庫索引中會出現數的深度過大導致的磁碟IO讀寫過於頻繁。

  1. Hash索引 : 使用hash表實現的,無法保障順序性,區間查詢無法使用索引,需要掃描全表。等值查詢的效率較高。
  2. 二叉查詢樹:可以解決排序問題,極端情況下會退化為連結串列。
  3. 平衡二叉樹:旋轉操作效率低
    • 非葉子節點最多擁有兩個子節點
    • 非葉子節值大於左邊子節點、小於右邊子節點
    • 樹的左右兩邊的層級數相差不會大於1
    • 沒有值相等重複的節點
  4. B樹 :B樹和平衡二叉樹稍有不同的是B樹屬於多叉樹又名平衡多路查詢樹(查詢路徑不只兩個)
  5. 紅黑樹: 對嚴格的平衡做了取捨和引入紅黑節點,解決了平衡二叉樹旋轉效率過低的問題,樹依然太深在磁碟場景下IO次數太多不符合預期。

AVL樹/紅黑樹

紅黑樹和AVL樹都是最常用的平衡二叉搜尋樹,它們的查詢、刪除、修改都是O(lgn) time

AVL樹和紅黑樹有幾點比較和區別:

  1. AVL樹是更加嚴格的平衡,因此可以提供更快的查詢速度,一般讀取查詢密集型任務,適用AVL樹。
  2. 紅黑樹更適合於插入修改密集型任務。
  3. 通常,AVL樹的旋轉比紅黑樹的旋轉更加難以平衡和除錯。

總結:

  1. AVL以及紅黑樹是高度平衡的樹資料結構。它們非常相似,真正的區別在於在任何新增/刪除操作時完成的旋轉操作次數。
  2. 兩種實現都縮放為a O(lg N),其中N是葉子的數量,但實際上AVL樹在查詢密集型任務上更快:利用更好的平衡,樹遍歷平均更短。另一方面,插入和刪除方面,AVL樹速度較慢:需要更高的旋轉次數才能在修改時正確地重新平衡資料結構。
  3. 在AVL樹中,從根到任何葉子的最短路徑和最長路徑之間的差異最多為1。在紅黑樹中,差異可以是2倍。
  4. 兩個都給O(log n)查詢,但平衡AVL樹可能需要O(log n)旋轉,而紅黑樹將需要最多兩次旋轉使其達到平衡(儘管可能需要檢查O(log n)節點以確定旋轉的位置)。旋轉本身是O(1)操作,因為你只是移動指標。

索引失效

  1. 模糊匹配前邊帶百分號 %like
  2. 索引列參與計算,使用了函式
  3. 非最左字首順序
  4. 使用is not null 或者 is null
  5. 使用不等於(!= 或者<>) [<>走全表掃描一般會更快]
  6. or操作有至少一個欄位沒有索引
  7. 回表查詢的結果集過大 [超過配置的最大範圍]

explain命令

  1. id:選擇識別符號
  2. select_type:表示查詢的型別
  3. table:輸出結果集的表
  4. partitions:匹配的分割槽
  5. type:表示表的連線型別
  6. possible_keys:表示查詢時,可能使用的索引
  7. key:表示實際使用的索引
  8. key_len:索引欄位的長度
  9. ref:列與索引的比較
  10. rows:掃描出的行數(估算的行數)
  11. filtered:按表條件過濾的行百分比
  12. Extra:執行情況的描述和說明

select_type/查詢型別

  1. SIMPLE(簡單SELECT,不使用UNION或子查詢等)
  2. PRIMARY(子查詢中最外層查詢,查詢中若包含任何複雜的子部分,最外層的select被標記為PRIMARY)
  3. UNION(UNION中的第二個或後面的SELECT語句)
  4. DEPENDENT UNION(UNION中的第二個或後面的SELECT語句,取決於外面的查詢)
  5. UNION RESULT(UNION的結果,union語句中第二個select開始後面所有select)
  6. SUBQUERY(子查詢中的第一個SELECT,結果不依賴於外部查詢)
  7. DEPENDENT SUBQUERY(子查詢中的第一個SELECT,依賴於外部查詢)
  8. DERIVED(派生表的SELECT, FROM子句的子查詢)
  9. UNCACHEABLE SUBQUERY(一個子查詢的結果不能被快取,必須重新評估外連結的第一行)

type

表示這個查詢訪問資料的方式,或者說MySQL查詢行的方式,MySQL手冊中稱為連線方式。
常用的型別有: ALL、index、range、 ref、eq_ref、const、system、NULL(從左到右,效能從差到好)

Extra

MySQL where語句的幾種應用方式

從好到壞依次為:

  • 在索引中使用Where來過濾不匹配的記錄 這是在儲存引擎層完成的
  • 使用索引覆蓋來掃描所需要的資料[Extra 中出現using index],直接從索引過濾不需要的記錄並返回命中結果,這是在MySQL伺服器層完成的事情.
  • 從資料表中返回資料,然後過濾不滿足要求的記錄[Extra列中出現 Using where],這是在MySQL伺服器層完成的事情,MySQL需要先從資料表讀出記錄然後過濾。