前言
臨近春節,這段時間閑來無事又讀了一些關于MySQL的文章和書籍,覺得受益良多,尤其是阿里巴巴丁奇的MySQL實戰45講,真的讓我感覺到有質的提升,以前看書看博客都是優先看索引部分,優化部分,都是一些作業中常用的知識點,但現在我對MySQL的底層越來越好奇,所以從MySQL的基礎架構開始學起,就有了這篇博客,
MySQL邏輯結構
大體來說,MySQL可以分為Server層和存盤引擎層兩部分,

Server層包括連接器、查詢快取、分析器、優化器、執行器等,涵蓋MySQL的大多數核心服務功能以及內置函式,
存盤引擎層負責資料的存盤和提取,它的架構模式是插件式,支持InnoDB、MyISAM、Memory等多個存盤引擎,從MySQL5.5.5開始,MySQL的存盤引擎默認是InnoDB,
MySQL的執行流程和組件作用
在執行這條查詢陳述句的時候:
mysql> select * from T where id = 10;
我們只知道輸入一條SQL,回傳一個結果,卻不知道這條陳述句在MySQL內部的執行程序,
接下來我會通過這條簡單的查詢陳述句,走一遍MySQL的執行流程,看一下每個組件的作用,
1、連接器
第一步,我們要先連接到這個資料庫上,就先要面對連接器,連接器負責跟客戶端建立連接、獲取權限、維持和管理連接的作用,命令一般如下:
mysql> mysql -u root -p
輸完以上命令,就要輸入連接MySQL的密碼,賬號密碼出錯會受到一個“Access denied for user”的錯誤,需要重新連接,
mysql是客戶端用來跟服務端建立連接的命令,在完成TCP握手后,連接器需要認證你的身份,這個時候就要輸入賬號和密碼,完成連接,
連接完成后,如果沒有后續的動作,這個連接就會處于空閑狀態,一般太長時間沒有動靜,連接器會自動斷開連接,這個時間由wait_timeout決定,默認時間為8個小時,
2、查詢快取
客戶端和服務端建立連接后,可以執行select陳述句,這個時候來到了Server層的查詢快取,
MySQL在接到select請求之后,會先去查詢快取看看之前是不是執行過這條陳述句,之前執行過陳述句及其結果會以key-value存放在記憶體中,key是查詢的陳述句,value是查詢的結果,如果你的查詢在查詢快取中找到key,則直接回傳查詢快取的value給客戶端,
如果查詢陳述句不在查詢快取中,就會繼續后面的執行流程,執行完成后,執行結果會被存入查詢快取中,但是在MySQL實戰45講中,作者建議我們不要使用查詢快取,為什么呢?因為查詢快取往往利大于弊,
查詢快取的失效非常頻繁,只要對一張表進行更新操作,這個表的所有查詢快取都會被清空,因此你建立起來的查詢快取還沒有使用就被清空了,對于更新壓力大的資料庫,查詢快取的命中率更低,
需要注意的是,從MySQL8.0開始,直接把整個查詢快取的功能洗掉掉,也就是說8.0開始沒有查詢快取這個功能了,
3、分析器
如果沒有命中快取,就要開始執行查詢陳述句,首先MySQL對你的查詢陳述句進行決議,
分析器會先做“詞法分析”,分析你的SQL,把查詢陳述句的“T”識別成“表名T”,把“id”識別成“列id”,
做完以上識別之后,MySQL開始做“語法分析”,根據語法規則判斷你輸入的SQL是否滿足MySQL的語法,
如果你的查詢陳述句寫錯了,就會收到“You hava an error in you SQL syntax”的錯誤提醒,比如你的查詢陳述句打少了一個“t”,
mysql> selec * from T where id = 10;
> 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'selec * from T' at line 1
一般語法錯誤會提示第一個出現錯誤的位置,所以你要關注"use near"后面的內容,
4、優化器
經過了分析器,MySQL就知道了你要干什么了,在開始執行之前,還需要經過優化器的處理,
優化器是在表中有多個索引的時候,決定使用哪個索引;或者在一個SQL中有多張表聯合查詢的時候,決定各個表的執行順序,比如你執行下面的陳述句:
mysql> select * from T1 inner join T2 on T1.id=T2.id where T1.b=10 and T2.c=20;
- 即可以從表T1取出b=10的記錄值id,再根據id關聯T2表,再判斷T2的c等于20的記錄
- 又可以從表T2取出c=20的記錄值id,再根據id關聯T1表,再判斷T1的b等于10的記錄
這兩個方法執行完的結果是一模一樣的,但是執行效率會有所不同,而優化器的作用是決定選擇使用哪一個方法,
MySQL資料庫使用的是基于成本的優化器,估算成本為CPU代價+IO代價,最后決定執行哪種方案,想更深入理解優化器,推薦你們讀《資料庫查詢優化器的藝術》,
5、執行器
優化器階段完成后,確定了執行方案后,就可以進入執行器階段,開始執行陳述句的時候,會先判斷你對這張表T有沒有執行查詢的權限,如果沒有,就會回傳沒有權限的錯誤,
mysql> select * from T where id = 10;
> 1142 - SELECT command denied to user 'god-jiang@localhost' for table 'T'
如果有權限,就繼續執行查詢操作,執行器會根據表的存盤引擎去使用引擎對應的介面,

執行程序為:
- 呼叫InnoDB引擎介面取表T的第一行,判斷id值是否等于10,如果不是則跳過,如果是則存到結果集中,
- 呼叫引擎介面取下一行,重復以上的相同邏輯,直到取到表T的最后一行,
- 執行器將上面的遍歷程序中所有滿足id=10的行組成結果集全部回傳給客戶端,
到這里,陳述句select * from T where id = 10就全部執行完成了,
知識點串起來
以上都是一個個組件的說明和講解,現在我把他們串起來方便大家理解,
select * from T where name = 'god-jiang';
按照上面講解的MySQL執行流程,這條陳述句的執行流程是這樣的:
- 通過連接器檢查當前賬號是否有select這張表的權限,如果沒有,就拋例外,
- 過了連接器,就到了分析器,一般SQL沒有語法錯誤,就會繼續往下走,
- 現在到了優化器,優化器會根據基于成本的優化器來決定執行哪種方案,
- 到了執行器,直接呼叫存盤引擎的介面,然后回傳結果給客戶端即可,
總結
今天根據select * from T where id = 10過了一遍MySQL的執行程序和內部組件,可以讓你對整個查詢的執行流程和各個組件有個了解,
參考資料
- MySQL實戰45講 - 林曉斌
- 《資料庫查詢優化器的藝術》
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/258705.html
標籤:其他
