天天CURD,你了解為了執(zhí)行SQL,MySQL用了怎樣的架構設計嗎?

大家好, 從今天開始我們開啟MySQL底層原理的探索里程,今天是第一篇我們將MySQL從一個黑盒狀態(tài)一點點撥云見日剖析來了解整個MySQL的架構設計和底層組件

image.png

把MySQL當作一個黑盒來執(zhí)行SQL

現(xiàn)在我們來看看, 對于研發(fā)工程師來說數(shù)據(jù)庫是什么東西?平時我們做系統(tǒng)開發(fā)時,一般情況下都會連接到一個MySQL數(shù)據(jù)庫上去,去執(zhí)行各種增刪改查語句。如下圖所示:


image.png

但是實際上我們在使用MySQL的過程中,總會遇到這樣那樣的一些問題,比如死鎖異常、SQL性能太差、MySQL gone away等等。在遇到MySQL數(shù)據(jù)庫的一些問題時,一般都會上網(wǎng)搜索博客,然后自己嘗試搗鼓著解決一下,最后解決了問題,可能也沒搞明白里面的原理。

因此我們就要去探索MySQL底層原理的方方面面,以及探索在解決MySQL各種生產(chǎn)實戰(zhàn)問題的時候,以及如何基于MySQL底層
原理去進行分析、排查和定位。

如何連接到MySQL:MySQL驅動

大家都知道,如果我們要訪問數(shù)據(jù)庫,必須得跟數(shù)據(jù)庫建立一個網(wǎng)絡連接,那么這個連接由誰來建立呢?答案就是MySQL驅動,它會在底層跟數(shù)據(jù)庫建立網(wǎng)絡連接,有網(wǎng)絡連接,接著才能去發(fā)送請求給數(shù)據(jù)庫服務器!如下圖所示:


image.png
數(shù)據(jù)庫連接池

那么我們來思考一個問題,一個golang系統(tǒng)難道只會跟數(shù)據(jù)庫建立一個連接嗎?這樣肯定是不行的, 對于一個稍微有點流量的站點來說,瞬時會有很多請求打過來,這個時候,都去競爭一個數(shù)據(jù)庫連接的話,性能肯定很低下。
那么如果golang在訪問數(shù)據(jù)庫的時候,都創(chuàng)建一個連接,執(zhí)行完后就釋放,這樣行不行?首先要明白的是數(shù)據(jù)庫連接是有上限的,因為每次建立一個數(shù)據(jù)庫連接都很耗時(tcp三次握手),好不容易建立好了連接,執(zhí)行完了SQL語句,你還把數(shù)據(jù)庫連接給銷毀了,下一次再重新建立數(shù)據(jù)庫連接,那肯定是效率很低下的 。


image.png

所以一般我們必須要用數(shù)據(jù)庫連接池,也就是說在一個池子里維持多個數(shù)據(jù)庫連接,讓多個進程使用里面的不同的數(shù)據(jù)庫連接去
執(zhí)行SQL語句,然后執(zhí)行完SQL語句之后,不要銷毀這個數(shù)據(jù)庫連接,而是把連接放回池子里,后續(xù)還可以繼續(xù)使用。
基于這樣的一個數(shù)據(jù)庫連接池的機制,就可以解決連接爭搶和效率問題,如圖所示:


image.png
MySQL數(shù)據(jù)庫的連接池

講到現(xiàn)在我們已經(jīng)知道,我們任何一個系統(tǒng)都會有一個數(shù)據(jù)庫連接池去訪問數(shù)據(jù)庫,也就是說這個系統(tǒng)會有多個數(shù)據(jù)庫連接,供程序并發(fā)
的使用。同時我們可能會有多個系統(tǒng)同時去訪問一個數(shù)據(jù)庫。
這個時候,我們將目光轉移到MySQL本身,對于多系統(tǒng)要與數(shù)據(jù)庫建立很多連接,那么MySQL必然也要維護與系統(tǒng)之間的多個連接才可以,所以,這里我們開始了解MySQL架構體系中的第一個環(huán)節(jié),就是連接池。

如下圖所示,實際上MySQL中的連接池就是維護了與系統(tǒng)之間的多個數(shù)據(jù)庫連接。除此之外,你的系統(tǒng)每次跟MySQL建立連接的
時候,還會根據(jù)你傳遞過來的賬號和密碼,進行賬號密碼的驗證,庫表權限的驗證。


image.png

講到這里,我們還是把MySQL當作一個黑盒在使用,我們只知道執(zhí)行了insert語句之后,在表里會多出來一條數(shù)據(jù);執(zhí)行了update語句之后,會對表里的數(shù)據(jù)進行更改;執(zhí)行了delete語句之后,會把表里的一條數(shù)據(jù)刪除掉;執(zhí)行了select語句之后,會從表里查詢一些數(shù)據(jù)出來。如果語句性能有點差?沒關系,在表里建幾個索引就可以了!

SQL線程:負責監(jiān)聽,讀取請求

從現(xiàn)在開始就要打破這種把數(shù)據(jù)庫當黑盒子的認知程度,要深入底層,去探索數(shù)據(jù)庫的工作原理以及生產(chǎn)問題的優(yōu)化手段!
現(xiàn)在我們的數(shù)據(jù)庫服務器的連接池中的某個連接接收到了網(wǎng)絡請求,假設就是一條SQL語句,那么我們先思考一個問題,
誰負責從這個連接中去監(jiān)聽網(wǎng)絡請求?誰負責從網(wǎng)絡連接里把請求數(shù)據(jù)讀取出來?
其實這個時候,一定得有一個線程去處理網(wǎng)絡連接,并由它來監(jiān)聽請求以及讀取請求數(shù)據(jù),比如從網(wǎng)絡連接中讀取和解析出來一
條我們的系統(tǒng)發(fā)送過去的SQL語句, 如下圖所示:


image.png

SQL接口:負責接收SQL語句

那么接下來著我們思考一下,當MySQL內部的工作線程從一個網(wǎng)絡連接中讀取出來一個SQL語句之后,此時會如何來執(zhí)行這個SQL語
句呢?
其實MySQL內部首先提供了一個組件,就是SQL接口(SQL Interface),它是一套執(zhí)行SQL語句的接口,專門用于執(zhí)行我們
發(fā)送給MySQL的那些增刪改查的SQL語句,因此MySQL的工作線程接收到SQL語句之后,就會轉交給SQL接口去執(zhí)行,如下圖。


image.png

查詢解析器:讓Mysql能看懂SQL

那么問題來了,SQL接口是如何執(zhí)行SQL語句呢?你直接把SQL語句交給MySQL,他怎么能看懂和理解這些SQL語句呢?
比如我們來舉一個例子,現(xiàn)在我們有這么一個SQL語句:

select id,name,age,sex from `user` where id=1;

我們用人腦是直接就可以處理一下,只要懂SQL語法的人,立馬大家就知道他是什么意思,但是MySQL是一個數(shù)據(jù)庫管理系統(tǒng),他沒法直接理解這些SQL語句!

  此時有一個關鍵的組件要出場了,那就是"查詢解析器"
這個查詢解析器(Parser)就是負責對SQL語句進行解析的,比如對上面那個SQL語句進行一下拆解,拆解
成以下幾個部分:
 1) 我們現(xiàn)在要從“users”表里查詢數(shù)據(jù)
 2) 查詢“id”字段的值等于1的那行數(shù)據(jù)
 3) 對查出來的那行數(shù)據(jù)要提取里面的“id,name,age”三個字段。
所謂的SQL解析,就是按照既定的SQL語法,對我們按照SQL語法規(guī)則編寫的SQL語句進行解析,
然后理解這個SQL語句要干什么事情

如下圖所示:


image.png

查詢優(yōu)化器:選擇最優(yōu)的查詢路徑

當我們通過SQL解析器理解了SQL語句要干什么之后,接著會找查詢優(yōu)化器(Optimizer)來選擇一個最優(yōu)的查詢路徑。這里我們可以用一個極為通俗簡單的例子,來理解一下所謂的最優(yōu)查詢路徑是什么。
我們現(xiàn)在理解了一個SQL想要干這么一個事兒:我們現(xiàn)在要從"users"表里查詢數(shù)據(jù),查詢id字段的值等于1的那行數(shù)據(jù),對查出來的那行數(shù)據(jù)要提取里面的"id,name,age"三個字段。
事情明白了,但是到底應該怎么來實現(xiàn)呢?這里我們來簡單分析下有以下兩種查詢路徑:

1) 直接定位到"users"表中的id字段等于1的一行數(shù)據(jù),然后查出來那行數(shù)據(jù)的"id,name,age"三個字段
的值就可以了
2) 先把"users"表中的每一行數(shù)據(jù)的"id,name,age"三個字段的值都查出來,然后從這批數(shù)據(jù)里過濾出來
id字段等于1的那行數(shù)據(jù)的"id,name,age"三個字段

其實我們會發(fā)現(xiàn),要完成這個SQL語句的目標,兩個路徑都可以做到,但
是哪一種更好呢?顯然感覺上是第一種查詢路徑更好一些。
所以查詢優(yōu)化器就是干這個的,它會針對你寫的幾十行、幾百行甚至上千行的復雜SQL語句生成查詢路徑樹,然后從里面選擇一條最優(yōu)的查詢路徑出來。相當于他會告訴你,你應該按照一個什么樣的步驟和順序,去執(zhí)行哪些操作,然后一步一步的把SQL語句就給完成了。如下圖所示:


image.png

存儲引擎接口,真正執(zhí)行SQL語句

這個時候把查詢優(yōu)化器選擇的最優(yōu)查詢路徑計劃交給底層的存儲引擎去真正的執(zhí)行。這個存儲引擎是MySQL的架構設計中很有”特色”的一個環(huán)節(jié)。
不知道你有沒有思考過,真正在執(zhí)行SQL語句的時候,要么更新數(shù)據(jù),要么查詢數(shù)據(jù),那么數(shù)據(jù)你覺得存放在哪里?
其實數(shù)據(jù)庫就是一個C、C++語言寫出來的系統(tǒng)而已,然后啟動之后也是一個進程,執(zhí)行他里面的各種代碼,也就是我們上面所說的那些東西。所以對數(shù)據(jù)庫而言,我們的數(shù)據(jù)要不然是放在內存里,要不然是放在磁盤文件里,沒什么特殊的地方!

   所以我們來思考一下,假設我們的數(shù)據(jù)有的存放在內存里,有的存放在磁盤文件里。那么問題來了,
我們已經(jīng)知道一個SQL語句要如何執(zhí)行了,但是我們現(xiàn)在怎么知道哪些數(shù)據(jù)在內存里?哪些數(shù)據(jù)在磁盤里?
我們執(zhí)行的時候是更新內存的數(shù)據(jù)?還是更新磁盤的數(shù)據(jù)?我們如果更新磁盤的數(shù)據(jù),是先查詢哪個磁盤
文件,再更新哪個磁盤文件?到這里是不是感覺一頭霧水?
所以這個時候就需要"存儲引擎"了,存儲引擎其實就是執(zhí)行SQL語句的,他會按照一定的步驟去查詢內存
緩存數(shù)據(jù),更新磁盤數(shù)據(jù),查詢磁盤數(shù)據(jù),等等,執(zhí)行諸如此類的一系列的操作
image.png

在MySQL的架構設計中,SQL接口、SQL解析器、查詢優(yōu)化器其實都是通用的,就是一套組件而已。
但是存儲引擎的話,他是支持各種各樣的存儲引擎的(MySQL支持插件式引擎),比如我們常見的InnoDB、MyISAM、Memory等等,我們是可以選擇使用哪種存儲引擎來負責具體的SQL語句執(zhí)行的。
當然現(xiàn)在MySQL5.7都是使用InnoDB存儲引擎的,至于存儲引擎的原理,后續(xù)我們也會深入一步一步分析的

執(zhí)行器:根據(jù)執(zhí)行計劃調用存儲引擎的接口

這個時候我們再來思考一個問題,既然存儲引擎可以幫助我們去訪問內存以及磁盤上的數(shù)據(jù),那么是誰來調用存儲引擎的接口呢?
我們是不是還漏了一個執(zhí)行器的概念呢?這個執(zhí)行器會根據(jù)優(yōu)化器選擇的執(zhí)行方案,去調用存儲引擎的接口按照一定的順序和步驟,就把SQL語句的邏輯給執(zhí)行了。
這里舉個例子,比如執(zhí)行器可能會先調用存儲引擎的一個接口,去獲取"users"表中的第一行數(shù)據(jù),然后判斷一下這個數(shù)據(jù)的
id字段的值是否等于我們期望的一個值,如果不是的話,那就繼續(xù)調用存儲引擎的接口,去獲取"users"表的下一行數(shù)據(jù)。就是基于上述的思路,執(zhí)行器就會去根據(jù)我們的優(yōu)化器生成的一套執(zhí)行計劃,然后不停的調用存儲引擎的各種接口去完成SQL語句的執(zhí)行計劃,這樣整個流程就串起來了,如下圖所示:


image.png

到這里,我們將MySQL內部是如何去執(zhí)行一條SQL的整個流程詳細的剖析了一遍,可以簡單了解了內部各個組件的作用。下面奉上一張極客時間中MySQL45講專欄關于MySQL執(zhí)行的邏輯架構圖:


Mysql的邏輯架構圖

下一篇我們將會講"從一條SQL更新語句來了解InnoDB存儲引擎的架構設計", 敬請期待。。。。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
禁止轉載,如需轉載請通過簡信或評論聯(lián)系作者。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,224評論 6 529
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 97,916評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,014評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,466評論 1 308
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,245評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,795評論 1 320
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,869評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,010評論 0 285
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,524評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,487評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,634評論 1 366
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,173評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 43,884評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,282評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,541評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,236評論 3 388
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,623評論 2 370

推薦閱讀更多精彩內容