原來一條select語句在MySQL是這樣執行的《死磕MySQL系列 一》

發表於2021-08-23

前言

咔咔閒談

看到蔣老師的第一篇文章後就收貨頗豐,真是句句戳中痛點。

令我記憶最深的就是為什麼知道了一個個技術點,卻還是用不好 ?不管是蔣老師所說的Redis還是本系列要展開學習的MySQL。

這是一個值得思考的問題,在大多數情況下,我們直接上百度搜尋MySQL事務、MySQL索引之類的詞彙。

上述問題當然也是MySQL的幾個核心問題之一,但如果我們都在不斷地學習這些大的方面,我們怎麼才能在學習某一個技能上有質的提升。

借用蔣老師的話術:“很多技術人都有一個誤區,就是隻注重零散的技術,沒有建立一個完整的知識架構,缺乏系統觀,然而,系統觀卻是至關重要的。在解決問題的時候,從某種意義上來說,擁有系統觀,就意味著你有依據、有章法去定位並解決問題。”

假如你對這些話也深有體會,那就跟咔咔一起建立一套MySQL的知識框架,對於這種思想也是第一次實戰,希望大家多多提意見。

一、從巨集觀的角度分析MySQL

首先看一張經典圖片

MySQL邏輯架構圖

這幅圖估計很多人都看到過,也是經典之作高效能MySQL裡邊的,如果有興趣可以先看一下電子版的(如需要電子版可聯絡咔咔),感覺自己能看進去了,再去買書也來的急。

閒話少說,進入正題。

上圖的客戶端可以直接理解為PHP、Java等。接下來,你會看到連線、執行緒處理。這一部分並不是MySQL所特有的,而且大多數客戶端、伺服器都具有類似的結構。

因此,一般而言,MySQL可以分為兩層:Server層和儲存引擎層。

Server層主要包括連線層、查詢快取、分析器、優化器、執行器等重要模組組成,這一層還包含了MySQL核心Api部分,比如常用的格式化時間、加密等。

儲存引擎大家都很熟悉,因為在面試中不止一次的問過大家Innodb、Myisam儲存引擎的不同。

所以想過沒有,MySQL為什麼會有這麼多的儲存引擎呢?

一切技術起源於當下問題,同樣在MySQL中也不例外。

MySQL在儲存引擎這一方面的架構是外掛式的,即可以隨意切換不固定,而且MySQL5.5版本儲存引擎已經預設為Innodb。

二、一條SQL執行要經過多少困難?

下圖是咔咔之前培訓時給發的資料

MySQL詳細架構圖

圖中還有一個熟悉的陌生人查詢快取模組,該模組在MySQL8.0中已不存在。

關於該模組為何要被刪除,後續的文章也將於大家交流。

首先,我們將大致瞭解當我們執行一條SQL語句時,如何在這個架構圖中執行。

2-1 聯結器

mysql -u root -p連線資料庫命令,在執行之後,你將需要輸入密碼。當完成經典的TCP握手之後,聯結器就開始發揮作用了。

如果碼錯誤時,則返回Access denied for user ‘root‘@‘localhost‘ (using password: YES,錯誤編碼1045。

如果連線資訊均正確,則此時將根據你輸入的使用者訪問許可權表來獲取該使用者的許可權,此處必須清楚,當你登入成功後,即使其他人修改了你的許可權,在這個連線未斷開之前你的許可權是不會發生改變的。

當你連線完成之後,如果你一直不做任何事情,執行show processlist將會看到一個sleep,表示空連線。

那麼你知道在MySQL中,如果連線成功後沒有進行任何操作,多久會被自動中斷?

可以執行show variables like 'wait_timeout';用於檢視時間。

檢視自動斷開時間

在MySQL中如果沒有特別說明,那麼所有的時間都是以秒為單位的,根據時間轉換可以得知空連線持續8小時。

2-2 查詢快取

你需要注意的是,MySQL8.0已經被取消了,這個問題不止說了一次了,特別是那些正在使用MySQL8.0以下版本的小夥伴要注意哈!當你切換到8.0時候,遇到這個問題不知道怎麼解決。

MySQL8.0為何取消查詢快取模組

這個模組的設計,把查詢語句作為key ,將結果作為value 進行快取,一旦這個表有更新,之前所有的快取都會被清除掉。這就像你辛辛苦苦寫的程式碼提交之後被別人覆蓋一樣難受。

MySQL8.0以下的版本提供了一個引數query_cache_type = enmand來控制是否要使用查詢快取,在設定完成後,預設的select語句將不會被快取。

如果確實可以使用部分場景,那麼你可以將sql_cache新增到select關鍵字之後。

如果一條select語句之前被快取過,那麼結果集在這裡就會直接返回,而沒有快取過的select語句就比較辛苦了,還要繼續自己的漫漫長路。

2-3 分析器

MySQL8.0之前,它會在進入分析器之前判斷是否快取,在MySQL8.0之後,聯結器驗證成功後就直接進入分析器。

分析器,根據字面意思來理解就是分析要執行的SQL語句是什麼,要做什麼。

比如執行select * from user where id = 1

MySQL首先根據select判斷這是一個查詢語句,然後將user識別為表名,id識別為欄位名,這個過程被稱為詞法分析

下一步,需要知道該SQL的語法是否正確,進行語法分析,如果語法不對你就會看到You have an error in your SQL syntax錯誤。通常,將在use near中找到該錯誤。

2-4 優化器

到了這一步,MySQL知道你要做什麼,但是要選擇最佳執行方案。

優化器都優化些什麼?

舉例來說:多個索引時選擇那個索引、多表關聯時連線順序。

現在你是否想知道,優化器將優化多表關聯的連線順序,那在寫SQL語句時是否就不必考慮連線順序呢?

當然不是,能讓MySQL少做事情就少做,還是一個準則用小表驅動大表。

2-5 執行器

通過要做什麼、怎麼做後這條SQL語句才會真正的被執行,先進行許可權驗證,若沒有許可權則直接返回許可權錯誤,否則根據表定義的儲存引擎,去使用對應引擎提供的介面。

三、總結

執行流程圖

上圖包含了正文的所有知識點,也是整個MySQL的大體執行流程圖,後期文章都將圍繞這幾個要點展開。

堅持學習、堅持寫作、堅持分享是咔咔從業以來所秉持的信念。但願文章在偌大的網際網路上能給你帶來一點幫助,我是咔咔,下期見。

相關文章