徹底搞懂MySql及其底層原理(更新中...)


背景

Mysql無疑是互聯網公司用的最多的數據庫了,它擁有開源、免費、學習成本低((#_<-))等優點,以至於被各大廠商青睞。理論上來說作為開發人員而不是專業的DB人員只需要掌握常用的增刪改查命令以滿足業務需求就行。不過,由於互聯網行業的興起,導致了公司的業務越來越復雜,數據量越來越龐大,再加上程序員這一職業越來越受到人們的青睞,許多人紛紛通過各大培訓機構轉行,就連考研學子也稱計算機專業為“宇宙機”,紛紛選擇跨專業考研。

無疑是這一越來越內卷的現象,催生了眾多公司對開發人員Mysql越來越高的要求。如今,隨便上某招聘網站搜索“Java開發工程師”職業要求,其中數據庫一欄基本都是:熟練使用數據庫,精通數據底層原理,索引數據結構,sql優化......

當我第一次看到這些,心里一萬個草泥馬,你這是在招DB還是Java開發?我就會個增刪改查還不行嗎?

如果你也有相似的經歷,對Mysql還只停留在增刪改查階段,想要輕松通過Mysql相關面試或者單純的想提升自己的sql認知水平。相信本文會帶給你耳目一新的感覺。

Ps 本人雖然科班出身,卻非常排斥滿文專業術語讓人一頭霧水,所以全文我會盡量用大白話形式展現,在必要的時候會有自己的繪圖以輔助讓文字更容易理解

從Mysql的引擎說起

存儲引擎是Mysql的核心,Mysql的存儲引擎是以插件的形式運行的,所以誕生了許多存儲引擎,如InnoDB、MyISAM、MEMORY、ARCHIVE、CSV等十多種。

不過從mysql5.5開始,默認存儲引擎就已經是InnoDB了,在之前是MyISAM,而我們僅僅只需要掌握這兩種就行(重點還是InnoDB)

MyISAM存儲引擎:

​ 作為mysql5.5以及之前的默認引擎,它具有以下特點:

(1)不支持事務;
(2)不支持外鍵,如果強行增加外鍵,不會提示錯誤,只是外鍵不其作用;
(3)對數據的查詢緩存只會緩存索引,不會像InnoDB一樣緩存數據,而且是利用操作系統本身的緩存;
(4)默認的鎖粒度為表級鎖,所以並發度很差,加鎖快,鎖沖突較少,所以不太容易發生死鎖;
(5)支持全文索引(MySQL5.6之后,InnoDB存儲引擎也對全文索引做了支持),但是MySQL的全文索引基本不會使用,對於全文索引,現在有其他成熟的解決方案,比如:ElasticSearch,Solr,Sphinx等。
(6)數據庫所在主機如果宕機,MyISAM的數據文件容易損壞,而且難恢復;

InnoDB存儲引擎

隨着軟件行業的不斷發展,尤其是互聯網行業的興起,以前的存儲引擎完全無法滿足業務需求,所以Mysql在5.5版本后就以此存儲引擎作為默認。InnoDB作為一款經典的存儲引擎,它能夠適應絕大多數企業的用途。

主要特點有:

(1)災難恢復性比較好;
(2)支持事務。默認的事務隔離級別為可重復度,通過MVCC(並發版本控制)來實現的。
(3)使用的鎖粒度為行級鎖,可以支持更高的並發;
(4)支持外鍵;
(5)配合一些熱備工具可以支持在線熱備份;
(6)在InnoDB中存在着緩沖管理,通過緩沖池,將索引和數據全部緩存起來,加快查詢的速度;
(7)對於InnoDB類型的表,其數據的物理組織形式是聚簇表。所有的數據按照主鍵來組織。數據和索引放在一塊,都位於B+數的葉子節點上;

你真的會建表嗎?

對於絕大多數程序員,每天的工作無疑都是對數據庫進行“增刪改查”。而表是我們存儲數據的核心,如果能夠根據業務建立一張合適的數據表,不僅能夠提升我們的開發效率,還會一定程度使數據庫查詢效率更高。

關於建表規范,推薦阿里巴巴數據庫設計規范:[阿里巴巴MySQL數據庫設計規范](數據庫設計規范-阿里雲開發者社區 (aliyun.com))

徹底說透索引

到底什么是索引?

對於索引,我相信絕大多數人都知道,也都用過。而且一般都會認為索引就相當於是書籍的目錄,可以方便我們快速查找數據。然而這樣認為並不完全正確。

索引應該是幫助MySQL高效獲取數據的排好序的數據結構。

沒錯,索引就是一種數據結構,包括:

  • 二叉樹,一種子節點最多為兩個的樹形數據結構。
  • 紅黑樹,一種從根節點到任意尾節點的路徑之差不超過1的平衡二叉樹
  • 哈希表,一種通過哈希算法直接存儲內存地址的數組
  • B樹,一種在節點存儲多條索引元素以及附帶數據的樹形結構
  • B+樹,B樹的變種,冗余存儲了索引元素,在葉子節點存儲了所有索引元素和附帶數據,且含有雙向指針

那么,索引到底是保存的什么呢?

一個完整的索引數據通常包含兩部分:排序的值和對應的數據

通常索引會按照索引字段進行排序並存儲

會根據編碼類型和排序規則進行排序,在我們創建數據庫時可以指定。

索引的數據具體保持的什么需要視情況而定,存儲引擎的不同以及索引類型的不同都會導致索引數據存儲的方式和結果不同

MyISAM存儲引擎中,主鍵索引對比非主鍵索引只有重復與否的區別,主鍵索引的值不可重復。所有索引存儲的數據其實是磁盤文件地址(數據結構同樣是B+樹,這種索引也稱為非聚族索引)。

但尋找到相應的索引后,就會根據磁盤文件地址尋找相應的真實數據並加載到內存中。

而在InnoDB存儲引擎中,如果是主鍵索引,那么在索引的數據區就是存儲這一行對應表中完整的數據。如果是非主鍵索引,那么數據區就是存儲的主鍵索引地址

顯而易見,InnoDB的主鍵索引雖然冗余了大量的數據,但減少了磁盤IO操作,也就提升了查詢效率,而這種索引也被稱為聚族索引。當我們根據主鍵索引查詢數據時,很顯然直接就從磁盤查詢到了,而根據非主鍵索引查詢數據時,需要額外查詢一次主鍵索引。

常見疑問🤔️:

  • 聚族索引既然冗余了這么多數據,那么進行增刪改操作豈不是不好維護?

    得確,聚族索引在維護時需要進行額外的操作。但通常來說,一個表的數據查詢的次數是要遠遠高於修改的次數,綜合考慮,維護成本帶來的收益還是相當可觀的。

  • 為什么InnoDB引擎推薦每個表都需要有主鍵,並且最好時整型自增主鍵?如果不建主鍵怎么樣?

    首先,InnoDB並不強制需要用戶建立主鍵,但它得確是必須存在主鍵的,當你沒創建主鍵時,mysql會選擇表中唯一的字段作為主鍵;若當你沒有唯一字段時,mysql會根據你的插入順序(俗稱行數)來作為主鍵。

    因為索引是根據索引字段來排序插入的,作為一顆B+樹來維護,既然排序,肯定整型自增的類型是天然排序的;如果不是整型,比如字符型,那么mysql就會根據字符編碼排序規則來排序,對比整型可以直接排序相當於是多了一個步驟。

  • 主鍵索引是必須的嗎?

    主鍵索引是必須的,它是跟主鍵相與相存的,並且一般由mysql自動創建。

  • 聚族索引相比非聚族索引誰快,為什么?

    聚族索引要更快,因為聚族索引可以直接在一個磁盤文件中尋找到索引數據,而非聚族索引需要跨文件尋找完整數據(俗稱“回表”)。

  • 在建立索引時我們還可以選擇hash索引,為什么一般很少用,它有使用場景嗎?

    hash索引數據結果類似於Java的HashMap,也會存在哈希碰撞。查詢效率通常來說比B+樹更高,但是只適合查找“=”,范圍類查找無法使用該類型索引。如果一張表的需求只會有等值查詢可以考慮哈希索引(這種需求應該很少吧)。

  • B+樹類索引是否支持范圍查找,原理如何?

    B+樹支持范圍查找,原理見下圖,我相信你會一目了然。。。

為什么需要索引?

通常來說在沒有緩存和索引的情況下,Mysql查找任何數據都是讀取磁盤文件進行IO操作,並進行逐行掃描,直到查找到目標數據。在數據量很大或關聯查詢較復雜的情況下會極大的影響查詢效率。

索引作為一種有序並且查詢效率極高的數據結構,可以快速的查找目標數據。

索引為何會失效?

索引最佳實踐

事務為什么重要?

什么是ACID?

高並發場景事務帶來的問題

鎖的詳解

事務隔離級別

深入理解MVCC與BufferPool緩存機制

MVCC是如何保證可重復讀?

nnodb引擎SQL執行的BufferPool緩存機制

進階

分布式事務

分庫分表


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM