MySQL 的基礎一(連接池, SQL接口, 查詢解析器, 查詢優化器, 存儲引擎接口, 執行器,)


MySQL數據庫的連接池

現在我們已經知道,我們任何一個系統都會有一個數據庫連接池去訪問數據庫,也就是說這個系統會有多個數據庫連接,供多線程並發的使用。同時我們可能會有多個系統同時去訪問一個數據庫,這都是有可能的。

所以當我們把目光轉移到MySQL的時候,我們要來思考一個問題,那就是肯定會有很多系統要與MySQL數據庫建立很多個連接,那么MySQL也必然要維護與系統之間的多個連接,所以 MySQL 架構體系中的第一個環節,就是連接池。

我們看下面的圖,實際上MySQL中的連接池就是維護了與系統之間的多個數據庫連接。除此之外,你的系統每次跟MySQL建立連接的時候,還會根據你傳遞過來的賬號和密碼,進行賬號密碼的驗證,庫表權限的驗證。

網絡連接必須讓線程來處理

現在假設我們的數據庫服務器的連接池中的某個連接接收到了網絡請求,假設就是一條SQL語句,那么大家先思考一個問題,誰負責從這個連接中去監聽網絡請求?誰負責從網絡連接里把請求數據讀取出來?

我想很多人恐怕都沒思考過這個問題,但是如果大家對計算機基礎知識有一個簡單了解的話,應該或多或少知道一點,那就是網絡連接必須得分配給一個線程去進行處理,由一個線程來監聽請求以及讀取請求數據,比如從網絡連接中讀取和解析出來一條我們的系統發送過去的SQL語句,如下圖所示:

SQL接口:負責處理接收到的SQL語句

MySQL 內部首先提供了一個組件,就是SQL接口(SQL Interface),他是一套執行SQL語句的接口,專門用於執行我們發送給MySQL的那些增刪改查的SQL語句

因此MySQL的工作線程接收到SQL語句之后,就會轉交給SQL接口去執行,如下圖。

查詢解析器:讓MySQL能看懂SQL語句

比如我們來舉一個例子,現在我們有這么一個SQL語句:

select id,name,age from users where id=1

這個SQL語句,我們用人腦是直接就可以處理一下,只要懂SQL語法的人,立馬大家就知道他是什么意思,但是MySQL自己本身也是一個系統,是一個數據庫管理系統,他沒法直接理解這些SQL語句!
所以此時有一個關鍵的組件要出場了,那就是 查詢解析器

這個查詢解析器(Parser)就是負責對SQL語句進行解析的,比如對上面那個SQL語句進行一下拆解,拆解成以下幾個部分:
1.我們現在要從“users”表里查詢數據
2.查詢“id”字段的值等於1的那行數據
3.對查出來的那行數據要提取里面的“id,name,age”三個字段。

所謂的SQL解析,就是按照既定的SQL語法,對我們按照SQL語法規則編寫的SQL語句進行解析,然后理解這個SQL語句要干什么事情,如下圖所示:

查詢優化器:選擇最優的查詢路徑

當我們通過解析器理解了SQL語句要干什么之后,接着會找查詢優化器(Optimizer)來選擇一個最優的查詢路徑。

但是我們可以用一個極為通俗簡單的例子,讓大家理解一下所謂的最優查詢路徑是什么。

就用我們剛才講的那個例子好了,我們現在理解了一個SQL想要干這么一個事兒:我們現在要從“users”表里查詢數據,查詢“id”字段的值等於1的那行數據,對查出來的那行數據要提取里面的“id,name,age”三個字段。

事是明白了,但是到底應該怎么來實現呢?

你看,要完成這個事兒我們有以下幾個查詢路徑(純屬用於大家理解的例子,不代表真實的MySQL原理,但是通過這個例子,大家肯定能理解所謂最優查詢路徑的意思)
1.直接定位到“users”表中的“id”字段等於1的一行數據,然后查出來那行數據的“id,name,age”三個字段的值就可以了
2.先把“users”表中的每一行數據的“id,name,age”三個字段的值都查出來,然后從這批數據里過濾出來“id”字段等於1的那行數據的“id,name,age”三個字段

上面這就是一個最簡單的SQL語句的兩種實現路徑,其實我們會發現,要完成這個SQL語句的目標,兩個路徑都可以做到,但是哪一種更好呢?顯然感覺上是第一種查詢路徑更好一些。

所以查詢優化器大概就是干這個的,他會針對你編寫的幾十行、幾百行甚至上千行的復雜SQL語句生成查詢路徑樹,然后從里面選擇一條最優的查詢路徑出來。

相當於他會告訴你,你應該按照一個什么樣的步驟和順序,去執行哪些操作,然后一步一步的把SQL語句就給完成了。

調用存儲引擎接口,真正執行SQL語句

最后一步,就是把查詢優化器選擇的最優查詢路徑,也就是你到底應該按照一個什么樣的順序和步驟去執行這個SQL語句的計划,把這個計划交給底層的存儲引擎去真正的執行。這個存儲引擎是MySQL的架構設計中很有特色的一個環節。

不知道大家是否思考過,真正在執行SQL語句的時候,要不然是更新數據,要不然是查詢數據,那么數據你覺得存放在哪里?

所以我們來思考一下,假設我們的數據有的存放在內存里,有的存放在磁盤文件里,如下圖所示。

那么現在問題來了,我們已經知道一個SQL語句要如何執行了,但是我們現在怎么知道哪些數據在內存里?哪些數據在磁盤里?我們執行的時候是更新內存的數據?還是更新磁盤的數據?我們如果更新磁盤的數據,是先查詢哪個磁盤文件,再更新哪個磁盤文件?

所以這個時候就需要存儲引擎了,存儲引擎其實就是執行SQL語句的,他會按照一定的步驟去查詢內存緩存數據,更新磁盤數據,查詢磁盤數據,等等,執行諸如此類的一系列的操作,如下圖所示。

MySQL的架構設計中,SQL接口、SQL解析器、查詢優化器其實都是通用的,他就是一套組件而已。

但是存儲引擎的話,他是支持各種各樣的存儲引擎的,比如我們常見的InnoDB、MyISAM、Memory等等,我們是可以選擇使用哪種存儲引擎來負責具體的SQL語句執行的。

當然現在MySQL一般都是使用InnoDB存儲引擎的,至於存儲引擎的原理,后續我們也會深入一步一步分析,大家不必着急。

執行器:根據執行計划調用存儲引擎的接口

那么看完存儲引擎之后,我們回過頭來思考一個問題,存儲引擎可以幫助我們去訪問內存以及磁盤上的數據,那么是誰來調用存儲引擎的接口呢?

其實我們現在還漏了一個執行器的概念,這個執行器會根據優化器選擇的執行方案,去調用存儲引擎的接口按照一定的順序和步驟,就把SQL語句的邏輯給執行了。

舉個例子,比如執行器可能會先調用存儲引擎的一個接口,去獲取“users”表中的第一行數據,然后判斷一下這個數據的“id”字段的值是否等於我們期望的一個值,如果不是的話,那就繼續調用存儲引擎的接口,去獲取“users”表的下一行數據。

就是基於上述的思路,執行器就會去根據我們的優化器生成的一套執行計划,然后不停的調用存儲引擎的各種接口去完成SQL語句的執行計划,大致就是不停的更新或者提取一些數據出來


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM