看完了MySQL小冊,我爲什麼強烈推薦?

本文有福利相送,做爲我鴿了這麼久的歉意。面試

朋友們我又回來了,距離上次發文應該過了一個月了,期間有不少我的的雜事,致使個人文章不能正常的更新,給你們說聲抱歉。算法

從上週開始吧,我開始看我在掘金好久之前買的一本小冊:《從根上理解Mysql是怎麼運行的》,本着買了會一半的原則,它一直在個人掘金裏面吃灰。sql

直到最近,看到一些Java交流羣裏MVCC這個名詞在個人時間線上反覆出現,我知道這是提示我去好好梳理一下Mysql相關的知識了。數據庫

因而我花了一週的時間把這本小冊從頭至尾的好好看了一遍,有些章節可能反覆看了四五遍,自認這本小冊裏的知識我搞懂了1/3,真的很慚愧,竟然還不到一半,由於這個號稱從根上理解Mysql的小冊涉及到了不少概念,短短一週真的很難所有梳理清楚。緩存

整體上來講,是一本乾貨滿滿的性價比好書,從行文內容上也能夠看出做者的功底,值得二刷三刷。(這本書貌似準備在機工出版了,已經說了半年了,估計就一個月以內了~)markdown

我不是來寫軟文,也不是搞推薦,很純粹的分享一下最近看這本書的感覺,這本書很適合會CRUD但對Mysq不甚瞭解的同窗。數據結構

簡單畫一個導圖給你們看一下這本書都講了什麼:併發

我將小冊講訴的全部內容分爲七部分,接下來我將根據導圖的各個部分說說個人見解。分佈式

InnoDB

你們若是查看過這本小冊的目錄,能夠發現其前四章都是關於一些基礎內容的,好比啓動Mysql-Server,使用Mysql-Client進行鏈接和更改字符集什麼的,因此這部分我並無標在導圖上,有一個大概瞭解就能夠。高併發

在這些基礎以後,就開始了小冊第一個硬菜:InnoDB原理的探究

InnoDB做爲咱們最經常使用的Mysql存儲引擎,做者對它的筆墨也是最多的,由於只有它支持事務,支持鎖,因此在這部分講述的不少內容都和後面的部分相呼應。

做者從一條記錄提及,給咱們娓娓道來了InnoDB內部的數據管理方式:

一條數據庫表記錄會以一種叫記錄格式的方式存儲,以5.7爲例列舉了MySQL中四種行格式的不一樣組成結構及其特性。

記錄格式說完以後,又要說說記錄格式放在哪了?記錄格式放在一個名爲的數據結構上,MySQL中有不少不一樣的頁用以不一樣的用處。

每一個頁是16KB大小,MySQL在讀取數據或者持久化數據的時候都是以頁爲基本單位,也就是說一次性最小會讀取或持久化16KB數據。

每次須要寫入數據時,都會向對應的數據頁申請內存,直至填滿以後會申請下一個頁,若是是刪除數據則會標記爲刪除,可是數據被刪除並不會移除此頁,而是被刪除的數據組成一個垃圾鏈表,等待新的數據來將其覆蓋

那麼頁說完了,頁又從屬於誰呢?這時又引入了表空間的概念。

一個表對應一個表空間文件(表名.ibd),這個表空間文件裏就是實際存放了數據的文件,數據記錄被頁管理,頁又被表空間管理,這是一個層層遞進的從屬關係。

可是由於用表空間直接管理頁能夠跨度太大(一個表空間對應全部表數據,可是一個頁才16KB,數據稍微大一點,就是一個表空間對應上萬甚至幾十萬的頁),因此表空間裏面又進行分層:區和組

64個頁對應一個區(64*16=1MB),256個區又對應一個組(256MB),這樣劃分以後一個邏輯從屬關係就變成了:記錄->數據頁->區->組->表空間

同時爲了加快加載速度,幾乎全部系統都會用到的緩存就被引入了-緩存池。

緩存池的引入大大提升了數據頁查詢的效率,畢竟磁盤IO太太太慢了,緩存池會在MySQL啓動時申請一塊內存做爲數據頁的緩存池(數據庫優化的時候能夠談談這個思路),同時根據算法來較好的控制緩存池裏的數據(最常訪問啊什麼的,這塊蠻複雜的)。

至此,InnoDB的基礎原理部分基本就是結束了,這部分我看下來最複雜的就是表空間部分,由於涉及到諸如索引之類的東西,能夠說表空間這節是整本小冊最難的,我看小冊評論區也都是如此想法。

索引

看小冊的時候原本就是抱着看索引的想法去的,可是沒想到索引的篇幅很短,只有兩章:索引原理和索引用法。

其實看小冊的時候,我通常都是對照着看的,看完做者寫的再去網上看看別人寫的,二者結合起來去理解。

索引這塊也是如此,可是做者寫的真是蠻通俗易懂的,索引就是在行記錄的基礎上進行主鍵排序,由於主鍵是有序的因此用主鍵做爲節點構成一顆B+樹,這顆B+樹的葉子節點就是全部的記錄,非葉子節點是一種名叫目錄樹的東西,能夠理解爲對葉子節點進行分組用的,由於是B+樹,因此使用二分查找能夠很快的查找到對應節點。

這種非葉子節點直接是行記錄數據的索引被稱爲聚簇索引,這種索引會在InnoDB中自動生成,且由於它葉子節點是全部的記錄,因此它也是很佔空間的東西。

咱們手動進行生成的索引叫作二級索引/輔助索引,這種索引生成後也會構成一個B+樹,可是此樹葉子節點並不記錄行數據,而是記錄對應行數據的主鍵,當你用二級索引拿到主鍵後,還要用主鍵從新搜索一次數據,這個過程叫作回表

若是建立二級索引時指定了多個列,這種索引叫作覆蓋索引

除了這些做者還順帶講了MyISAM的索引,它沒有聚簇索引都是二級索引,但二級索引和InnoDB的又有些不一樣,MyISAM的索引中記錄的不是主鍵而是行號,能夠經過對行號直接找到對應數據,這樣就少了一次回表過程。


懂了索引以後,再去看索引用法的注意事項就簡單多了~,好比:

  1. 索引列的類型儘可能小(減小創建索引耗費的空間)
  2. 刪除表中的重複和冗餘索引(索引列只會用到一個索引)
  3. 數據庫主鍵自增(避免主鍵無序,這樣會頻繁打亂B+樹的節點,由於B+樹依靠主鍵排序)
  4. where 條件儘可能索引字段的順序和建立聯合索引時字段順序一致(由於覆蓋索引建立是按照多個索引字段值從左到右進行排序的)
  5. 模糊匹配指定左前綴能夠用到索引(由於索引值排序時是按照從左到右,因此若是左側值指定了也能夠用到索引縮小範圍)

還有不少其餘的注意事項,這塊網上基本說的都夠了,我這裏再也不贅述,避嫌。

單表的訪問方式

單表的訪問方式,咋一聽很難理解的一個名詞,實際上是MySQL的設計者給不一樣的查詢設立了不一樣的叫法,好比用主鍵查詢速度很是快,這種叫const,意爲常量級查詢,複雜度能夠忽略掉。

這些都是一些知道了解的東西,由於算是一種規定,同時這部分是Explain的鋪墊,Explain會用到這裏面的知識。

Explain

Explain的知識網上博客講的也很清楚了,由於都是一些概念性的知識,我之前學MySQL的時候看的周陽的課,裏面也有講到Explain相關知識。

它主要是列出了一條查詢語句都走了哪些索引,影響了多少行數,我的以爲其實效用不大,由於一條SQL交給執行器去執行以後,會有優化器進行優化,優化過的SQL可能已經和原來你編寫的不同了,須要瞭解優化器優化過程才能看懂這個。

這種狀況你可使用optimizer_trace去查看SQL的執行過程來知道優化器都作了哪些事。

也能夠用其餘方式好比:show status like '%last_query_cost%'

這條語句能夠查詢上條查詢語句使用了多少成本,在SQL優化器對一個語句進行優化時會嘗試計算不一樣方案花費了多少成本,最終使用最少成本的那個優化方案,我以爲這種方式能夠比較直觀的對比本身編寫的兩個SQL的性能差距。

子查詢優化

在優化器優化這塊,小冊主要講了優化器進行優化的一些方案,不過主要講的仍是子查詢的優化方案。

事務

InnoDB基礎,索引,事務和鎖,能夠說是看完這本小冊必需要了解的四大塊了。

事務裏的概念不少,ACID就不說了,既然是講原理的書,那做者的筆墨就主要用在MySQL用了什麼方案來保證事務和事務的回滾

MySQL使用redo日誌來記錄事務執行中的語句,用undo日誌記錄語句執行前記錄的值,同時每一個事務都有一個全局ID。

redo日誌能夠保證系統哪怕崩潰了,重啓回來以後還能根據裏面的日誌恢復到原樣,undo則能夠保證須要回滾時有對應的記錄,undo還有一個做用,就是用來作MVCC。

MVCC(Mutil-Version Concurrency Control)-多版本併發控制,它是MySQL中用來解決併發讀寫的問題的一種方案。

在高併發的程序中,數據庫每每會同時開啓多個事務,執行過程當中多個事務交替執行,這就可能會出現事務併發問題:髒寫,髒讀,不可重複讀和幻讀。

這裏咱們再來複習一下這四個概念:

  1. 髒寫:一個事務修改了另外一個未提交事務修改過的數據
  2. 髒讀:一個事務讀到了另外一個事務未提交修改過的數據
  3. 不可重複讀:一個事務能讀到此事務開啓後其餘事務提交修改的值
  4. 幻讀:一個事務中兩條一樣的查詢條件進行查詢時,後讀到的數據比前一次多

這四個問題均可以經過鎖來解決,可是這樣的話性能必然是會降低的,因此在MySQL中選擇這樣作:

髒寫通常是由鎖來完成的,也就是一個時間點只有一個事務對一條記錄進行寫,避免髒寫。

髒讀,不可重複讀,幻讀則能夠由MVCC來控制,加強MySQL的併發性能,其原理是經過undo日誌維護了一個版本鏈,版本鏈每一個版本上面都有一個事務id來標識這個版本是由哪一個事務修改的,當前事務進行查詢時會根據當前事務id進行計算能夠看到這個版本鏈上的哪些記錄,從而去避免髒讀,不可重複讀和幻讀。

網上有些解讀MVCC的時候說這是版本鏈+樂觀鎖,看了小冊以後我在網上翻到了MySQL中關於這塊的源碼,和小冊上面講訴的同樣,是經過計算(或者說判斷)來決定能看到哪一個版本,樂觀鎖通常是比較新值和舊值,實際狀況和樂觀鎖不太相像。

事務這塊看完以後,發現數據庫常問的MVCC也沒有那麼神祕,能夠說是一句話就能說清的事。並且後來我突然想起來seata這個分佈式事務的AT模式,它的原理實現其實就和MySQL裏面的事務原理幾乎是同樣的。

有了前面的鋪墊以後,看鎖這一章會簡單許多,可是小冊上面的鎖這一章僅僅是介紹了鎖的分類,也就是說日常MySQL在用鎖的時候通常會用到哪些鎖,他們分別有什麼特性,並無去深刻的去分析兩個事務同時修改一條記錄的狀況下鎖是怎麼作的。

可是並非說做者沒寫,而是寫在公衆號裏面了,,,關注公衆號以後能夠去看有三篇加鎖實戰分析的文章。

鎖其實能夠經過兩個維度來劃分:粒度和特性。(固然這是我本身的理解)

  • 粒度:根據影響的範圍能夠分爲行級和表級。
  • 特性:根據鎖的特性能夠分爲獨佔或共享。

兩個維度組合一下通常就是四種:行級獨佔鎖、行級共享鎖、表級獨佔鎖和表級共享鎖。

除了這幾種鎖的具體實現,還介紹了鎖在內存中的結構,雖然我前面說了這章很重要,但我本身也沒有太過於細看,由於都是概念性須要記憶的東西。

其實這章結合公衆號的加鎖實戰分析的文章是比較好的,這章就像是鎖實戰的先行知識,否則你直接去看鎖實戰,各類概念一上來恐怕給人搞得頭都大了。

小結

這篇文章給我寫的很是尷尬,由於有不少想多寫出來的知識又不能寫(文章內容最多隻能由30%知識來源於小冊),因此我原本是想從邏輯上詳細給你們講講這本小冊的內容,可是又得避嫌(侵權啊,抄襲啊),最後就感受有點有始無終了(極力推薦查看個人導圖)。

不過像高頻率的一些知識點,我仍是寫到的了,好比索引原理和事務原理(不過有點簡化),大部分開發應該是都沒有這個知識深度,若是能好好記憶下里面的內容,面試的時候其實能夠往深了說,能把一點說深總比你說一堆淺顯易懂的知識點來的有用。

整體來講這本小冊仍是比較推薦的,是一本深挖原理的書,有些知識點好比bin log這種偏應用層的沒有講到,其餘的基本上都是很詳細了,用一下小冊優惠碼應該不到20塊錢,性價比很高。

文章開頭也說了,本文有一點點福利,給你們抽三個小冊六折碼(非贊助,都是我以前參加徵文活動攢的),鑑於上次抽獎的教訓(由於沒有私信,遲遲聯繫不上中獎者),此次打算轉移到公號去抽獎。

  • 只需關注個人同名公衆號(和耳朵),回覆抽獎就有專屬的抽獎鏈接,十月一日中午十二點開獎。
  • 還有個人MySQL思惟導圖文件,回覆MySQL關鍵字就能獲取腦圖。

好了,今天的文章就先到這,歡迎你們點贊支持,我是和耳朵,知識輸出,共同成長。

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息