MySQL的Innodb和myisam儲存引擎(持續更新)

MySQL存儲引擎的問題一直在面試的中頻繁出現,理解MySQL的存儲引擎的工作原理有助於在使用MySQL的過程中對查詢原理理解更加深刻。

innodb:目前MySQL的默認存儲引擎,也是使用最爲廣泛的存儲引擎,特點:

  • 支持事務,支持外鍵,一致性非鎖定讀,行級鎖的設定

    • 事務:一組原子性的操作,這組操作要麼全部發生並完成,要麼全部都不發生。事務把數據庫從一種一致性狀態轉換爲另一種一致性狀態。
      • 事務的特性:事務具有ACID四種特性,即原子性、一致性、隔離性、持久性
        • 原子性(A):只一個不可分割的操作,要麼全部正確執行,要麼全部都不執行。
        • 一致性(C): 指事務從開始到結束後,數據庫的完整性約束沒有被破壞。
          • 完整性約束:用於確定關係型數據庫裏面數據的完整性和一致性。
        • 隔離性(I):每個讀寫事務之間是分開的,在事務提交前對其他事務是不可見的。
        • 持久性(D):指事務一旦提交,其改變結果就是永久性的,即使宕機也能恢復。
    • 外鍵:用於與其他表建立連接,一個表的外鍵有可能是另外一個表的主鍵,所以在刪除時需要做一下確認。
    • 一致性非鎖定讀:是innodb通過多版本控制的方式讀取當前執行時間數據庫中的數據,如果被讀的數據行被加了排它鎖,在讀取該行數據時並不會等待數據的釋放,而是讀取改行的一個快照數據。
    • 行級鎖的設定:行鎖大幅度提高了多用戶併發操作的性能。但是InnoDB的行鎖,只是在WHERE的主鍵是有效的,非主鍵的WHERE都會鎖全表的
  • innodb存儲引擎採用聚集的方式存儲,因此每張表的存儲順序都是按主鍵的順序存儲的。如果沒有爲表指定主鍵,那麼innodb會爲每一行生成一個6字節的ROWID並以此作爲主鍵。想要理解聚集的存儲方式可以參考理解InnoDB的聚集索引

  • innodb存儲引擎通過MVCC(多版本併發控制)獲得高併發性,並提供了插入緩衝、二次寫、自適應hash索引和預讀等高性能、高可用功能。

    • MVCC多版本併發控制:提供了一致性讀不加鎖的重要特性,這樣一致性讀不會阻塞更新,從而提升了數據庫的性能。更多關於MVCC機制可以參考InnoDB的MVCC機制
    • 插入緩衝:Insert Buffer 用於非聚集索引的插入和更新操作。先判斷插入的非聚集索引是否在緩存池中,如果在則直接插入,否則插入到 Insert Buffer 對象裏。再以一定的頻率進行 Insert Buffer 和輔助索引葉子節點的 merge 操作,將多次插入合併到一個操作中,提高對非聚集索引的插入性能。
      • 使用插入緩衝的兩個條件:(1)索引是輔助索引;(2)索引不唯一。如果索引唯一還要去查找索引頁進行檢查唯一性,就失去了 Insert Buffer 離散插入的性能
    • 二次寫:如果數據庫發生宕機時,可以通過重做日誌對該頁進行恢復,但是如果該頁本身已經損壞了,進行重做恢復是沒有意義的。因此引入了"二次寫"方案,提高數據頁的穩定性。
    • 自適應哈希(hash)索引:InnoDB 會監控對錶上各個索引頁的查詢,如果觀察到通過哈希索引可以帶來性能提升,則自動建立哈希索引。自適應哈希索引通過緩存池的 B+ 樹頁構造而來,因此建立速度很快。
    • 預讀機制:就是發起一個I/O請求,異步地在緩衝池中預先回遷若干個頁面(預計很快就會需要的頁面),這些請求在一個範圍內引入所有頁面。
  • innodb存儲引擎默認的隔離級別爲重複性讀,並採用間歇鎖來避免幻讀。

    • 隔離級別:SQL標準定義了4類隔離級別,包括了一些具體規則,用來限定事務內外的改變哪些是可見的,哪些是不可見。低級別的隔離級一般支持更高的併發處理,並擁有更低的系統開銷。
      • Read Uncommitted(讀取未提交內容)
        在該隔離級別,所有事務都可以看到其他未提交事務的執行結果。本隔離級別很少用於實際應用,因爲它的性能也不比其他級別好多少。讀取未提交的數據,也被稱之爲髒讀(Dirty Read)
      • Read Committed(讀取提交內容)
        這是大多數數據庫系統的默認隔離級別(但不是MySQL默認的)。它滿足了隔離的簡單定義:一個事務只能看見已經提交事務所做的改變。這種隔離級別也支持所謂的不可重複讀(Nonrepeatable Read),因爲同一事務的其他實例在該實例處理其間可能會有新的commit,所以同一select可能返回不同結果。
      • Repeatable Read(可重讀)
        這是MySQL的默認事務隔離級別,它確保同一事務的多個實例在併發讀取數據時,會看到同樣的數據行。不過理論上,這會導致另一個棘手的問題:幻讀Phantom Read)。簡單的說,幻讀指當用戶讀取某一範圍的數據行時,另一個事務又在該範圍內插入了新行,當用戶再讀取該範圍的數據行時,會發現有新的“幻影”行。InnoDB和Falcon存儲引擎通過多版本併發控制(MVCC,Multiversion Concurrency Control)機制解決了該問題。
      • erializable(可串行化)
        這是最高的隔離級別,它通過強制事務排序,使之不可能相互衝突,從而解決幻讀問題。簡言之,它是在每個讀的數據行上加上共享鎖。在這個級別,可能導致大量的超時現象和鎖競爭。
      • 這四種隔離級別採取不同的鎖類型來實現,若讀取的是同一個數據的話,就容易發生問題。例如: 髒讀(Drity Read):某個事務已更新一份數據,另一個事務在此時讀取了同一份數據,由於某些原因,前一個RollBack了操作,則後一個事務所讀取的數據就會是不正確的。不可重複讀(Non-repeatable read):在一個事務的兩次查詢之中數據不一致,這可能是兩次查詢過程中間插入了一個事務更新的原有的數據。幻讀(Phantom Read):在一個事務的兩次查詢中數據筆數不一致,例如有一個事務查詢了幾列(Row)數據,而另一個事務卻在此時插入了新的幾列數據,先前的事務在接下來的查詢中,就會發現有幾列數據是它先前所沒有的。

myisam:在MySQL 5.1 及之前的版本,MyISAM是默認引擎。MyISAM提供的大量的特性,包括全文索引、壓縮、空間函數(GIS)等,但MyISAM並不支持事務以及提供行級鎖,並且一個毫無疑問的缺陷是崩潰後無法安全恢復。

  • 不支持事務,表級鎖的設計,支持全文索引(innodb5.6版本後支持),MyISAM允許沒有主鍵的表存在
    • 表級鎖:只支持表級鎖,用戶在操作myisam表時,select,update,delete,insert語句都會給表自動加鎖,如果加鎖以後的表滿足insert併發的情況下,可以在表的尾部插入新的數據。
    • 全文索引:如果希望通過關鍵詞的匹配來進行查詢過濾,那麼就需要基於相似度的查詢,而不是原來的精確值的比較,全文索引就是爲這種場景所設計的
  • myisam的存儲結構會在磁盤上分我三個文件進行存儲,分別是:.frm文件用於保存表格定義;MYD文件用於保存數據;MYI文件用於存儲索引
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章