關(guān)鍵字
基礎(chǔ)架構(gòu),宏觀理解
基礎(chǔ)架構(gòu)
要學(xué)習(xí) MySQL ,首先你要在宏觀上了解它的架構(gòu)。這樣,當(dāng)你在執(zhí)行一條命令的時候,會有一種“造物主視角”,同時,這種視角也會給你更加深刻的洞察力。在這里,我們就看一看,在你輸入一條查詢語句的時候,MySQL 中都發(fā)生了什么。
0.基礎(chǔ)架構(gòu)圖:
專欄的作者給出了 MySQL 的基本架構(gòu)示意圖:

大體上,MySQL 分為 Sever層 和存儲引擎層兩個部分:
- Sever層:包括連接器、查詢緩存、分析器等。它涵蓋了 MySQL 的大多數(shù)核心服務(wù)功能,以及所有的內(nèi)置函數(shù)。所有的跨存儲引擎的功能都在這一層實(shí)現(xiàn),如:觸發(fā)器、視圖等。
- 存儲引擎層:負(fù)責(zé)數(shù)據(jù)的存儲和提取。其架構(gòu)模式是插件式的,支持多種存儲引擎?,F(xiàn)在一般默認(rèn)使用 InnoDB引擎,除此之外,還有 Memory 等引擎。
不同引擎存取數(shù)據(jù)的方式不同,支持的功能也不同。你可以在 create table 語句中使用 engine = xxx 指定引擎。
1.連接器
- 連接器負(fù)責(zé)跟客戶端建立連接、獲取權(quán)限、維持和管理連接。
mysql -h$ip -P$port -u$user -p
- 首先,mysql 和服務(wù)器進(jìn)行 TCP連接,握手之后,會對你對身份進(jìn)行驗(yàn)證。認(rèn)證需要用戶名和密碼。
- 如果認(rèn)證通過,連接器會到權(quán)限表中查找你擁有的權(quán)限。之后你的所有權(quán)限,都依賴于此。
- 使用 show processlist 可以查看數(shù)據(jù)庫的連接狀況。
- 客戶端如果長時間沒有動靜,連接器會自動斷開。這個時間由參數(shù) wait_timeout 控制,默認(rèn) 8 小時。
- 長連接:連接成功后,如果客戶端持續(xù)請求,則一直使用同一個連接。
- 短連接:每次執(zhí)行完很少的幾次查詢后就斷開連接。
- 推薦使用長連接。但是 MySQL 執(zhí)行中的的臨時內(nèi)存是管理在連接對象中的,所以使用長連接可能導(dǎo)致內(nèi)存占用過大。
你可以使用兩種方法解決:定期斷開和重連;執(zhí)行較大操作后,使用 mysql_reset_connection 重新初始化連接。
2.查詢緩存
- MySQL 拿到查詢請求后,會先到緩存中查找。其邏輯和我們常說的緩存邏輯類似。
- 任何更新操作都會使緩存失效,因此緩存的命中率非常低。
- 建議你不要使用,且在 8.0 版本后直接刪除了緩存功能。
3.分析器
- 如果沒有命中緩存,就要開始執(zhí)行語句。MySQL 使用分析器對 SQL 語句進(jìn)行解析。
- 詞法分析:識別 SQL 語句中的字符串分別是什么,代表什么。
- 語法分析:依據(jù)詞法分析的結(jié)果,判斷這個 SQL 語句是否滿足 MySQL 語法。
4.優(yōu)化器
- 經(jīng)過分析器分析之后,MySQL 知道你要做什么了。但是在執(zhí)行之前,要先經(jīng)過優(yōu)化器的處理。
- 同樣一條語句可以有多種執(zhí)行方式,其效率不同,而優(yōu)化器會決定選擇使用哪個方案。例如:
mysql> select * from t1 join t2 using(ID) where t1.c=10 and t2.d=20;
優(yōu)化器會選擇先查詢 t1 表還是 t2 表。
5.執(zhí)行器
- 通過分析器知道了做什么,通過優(yōu)化器知道了該怎么做,而執(zhí)行器會具體執(zhí)行語句。
- 首先,執(zhí)行器會做權(quán)限驗(yàn)證。
- 驗(yàn)證通過,執(zhí)行器會根據(jù)引擎的定義,使用引擎提供的接口,例如執(zhí)行下面的語句:
mysql> select * from T where ID=10;
ERROR 1142 (42000): SELECT command denied to user 'b'@'localhost' for table 'T'
在表 T 中,ID 字段沒有索引,執(zhí)行流程如下:
1.調(diào)用 InnoDB 引擎接口取這個表的第一行,判斷 ID 值是不是 10,如果不是則跳過,如果是則將這行存在結(jié)果集中;
2.調(diào)用引擎接口取“下一行”,重復(fù)相同的判斷邏輯,直到取到這個表的最后一行。
3.執(zhí)行器將上述遍歷過程中所有滿足條件的行組成的記錄集作為結(jié)果集返回給客戶端。
4.至此,這個語句就執(zhí)行完成了。
- 通過查詢?nèi)罩镜?rows_examined 字段,可以查看引擎掃描的行數(shù)(具體會有出入,以后會詳細(xì)說明)
小結(jié)
今天我們學(xué)習(xí)了 MySQL 的邏輯架構(gòu),這可以讓你對一條 SQL 語句的執(zhí)行過程有一個初步印象。
專欄老師的思考題:
我給你留一個問題吧,如果表 T 中沒有字段 k,而你執(zhí)行了這個語句 select * from T where k=1, 那肯定是會報(bào)“不存在這個列”的錯誤: “Unknown column ‘k’ in ‘where clause’”。你覺得這個錯誤是在我們上面提到的哪個階段報(bào)出來的呢?
解答:
分析器,Oracle會在分析階段判斷語句是否正確,表是否存在,列是否存在等。MySQL也類似。
以上就是 MySQL 的基礎(chǔ)架構(gòu),希望你能從全局思考。
注:本文章的主要內(nèi)容來自我對極客時間app的《MySQL實(shí)戰(zhàn)45將》專欄的總結(jié),我使用了大量的原文、代碼和截圖,如果想要了解具體內(nèi)容,可以前往極客時間