MySQL體系架構

1. 背景

剛入行時,大部分Java工程師對MySQL停留在一個黑盒的認識,包括我自己。最近一段時間,這幾年通過項目實踐與不斷反思,對MySQL的新認知提升到一個新層次,供大家分享。

下圖是初始階段的認識,就是對數據庫建庫、建表、建索引,然後執行增刪改查操作。

2. 數據庫驅動

大家都知道,我們如果要在Java系統中去訪問一個MySQL數據庫,必須得在系統的依賴中加入一個MySQL驅動,有了這個MySQL驅動,才能跟MySQL數據庫建立連接,然後執行各種SQL語句。下面這段maven配置中就引入了一個MySQL驅動。這裏的mysql-connector-java就是面向Java語言的MySQL驅動。

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.12</version>
</dependency>

如果我們要訪問數據庫,必須得跟數據庫建立一個網絡連接,那麼這個連接由誰來建立呢?其實答案就是這個MySQL驅動,他會在底層跟數據庫建立網絡連接,有網絡連接,接着才能去發送請求給數據庫服務器!我們看下圖。

3. 數據庫連接池

一個Java系統難道只會跟數據庫建立一個連接嗎?這個肯定是不行的,假設我們用Java開發了一個Web系統,是部署在Tomcat中的,那麼Tomcat本身肯定
是有多個線程來併發的處理同時接收到的多個請求的,我們看下圖

這個時候,如果Tomcat中的多個線程併發處理多個請求的時候,都要去搶奪一個連接去訪問數據庫的話,那效率肯定是很低的,那麼如果Tomcat中的每個線程在每次訪問數據庫的時候,都基於MySQL驅動去創建一個數據庫連接,然後執行SQL語句,再銷燬這個數據庫連接,這是否可行呢?因爲每次建立一個數據庫連接都很耗時,好不容易建立好了連接,執行完了SQL語句,你還把數據庫連接給銷燬了,下一次再重新建立數據庫連接,那肯定是效率很低下的!

所以一般我們必須要使用一個數據庫連接池,也就是說在一個池子裏維持多個數據庫連接,讓多個線程使用裏面的不同的數據庫連接去執行SQL語句,然後執行完SQL語句之後,不要銷燬這個數據庫連接,而是把連接放回池子裏,後續還可以繼續使用。基於這樣的一個數據庫連接池的機制,就可以解決多個線程併發的使用多個數據庫連接去執行SQL語句的問題,而且還避免了數據庫連接使用完之後就銷燬的問題,我們看下圖的說明。

常見的數據庫連接池有DBCP,C3P0,Druid。其實不光是Java系統,如果你是一個Python、Ruby、.NET、PHP的程序員,這個系統與數據庫的交互本質都是一樣的,都是基於數據庫連接池去與數據庫進行交互。

4. MySQL數據庫的連接池

現在我們已經知道,我們任何一個系統都會有一個數據庫連接池去訪問數據庫,也就是說這個系統會有多個數據庫連接,供多線程併發的使用。同時我們可能會有多個系統同時去訪問一個數據庫,這都是有可能的。
所以當我們把目光轉移到MySQL的時候,我們要來思考一個問題,那就是肯定會有很多系統要與MySQL數據庫建立很多個連接,那麼MySQL也必然要維護與系統之間的多個連接,所以MySQL架構體系中的第一個環節,就是連接池。
我們看下面的圖,實際上MySQL中的連接池就是維護了與系統之間的多個數據庫連接。除此之外,你的系統每次跟MySQL建立連接的時候,還會根據你傳遞過來的賬號和密碼,進行賬號密碼的驗證,庫表權限的驗證。

6. 數據庫線程

現在假設我們的數據庫服務器的連接池中的某個連接接收到了網絡請求,假設就是一條SQL語句,那麼大家先思考一個問題,誰負責從這個連接中去監聽網絡請求?誰負責從網絡連接裏把請求數據讀取出來?網絡連接必須得分配給一個線程去進行處理,由一個線程來監聽請求以及讀取請求數據,比如從網絡連接中讀取和解析出來一條我們的系統發送過去的SQL語句。

7. SQL接口

接着我們來思考一下,當MySQL內部的工作線程從一個網絡連接中讀取出來一個SQL語句之後,此時會如何來執行這個SQL語句呢?
其實SQL是一項偉大的發明,他發明了簡單易用的數據讀寫的語法和模型,哪怕是個產品經理,或者是運營專員,甚至是銷售員,即使他不會技術,他也能輕鬆學會使用SQL語句,因此MySQL的工作線程接收到SQL語句之後,就會轉交給SQL接口去執行。

8. 查詢解析器

接着下一個問題來了,SQL接口怎麼執行SQL語句呢?你直接把SQL語句交給MySQL,他能看懂和理解這些SQL語句嗎?比如我們來舉一個例子,現在我們有這麼一個SQL語句:select id,name,age from users where id=1這個SQL語句,我們用人腦是直接就可以處理一下,只要懂SQL語法的人,立馬大家就知道他是什麼意思,但是MySQL自己本身也是一個系統,是一個數據庫管理系統,他沒法直接理解這些SQL語句!所以此時有一個關鍵的組件要出場了,那就是查詢解析器。所謂的SQL解析,就是按照既定的SQL語法,對我們按照SQL語法規則編寫的SQL語句進行解析,然後理解這個SQL語句要幹什麼事情

9. 查詢優化器

當我們通過解析器理解了SQL語句要幹什麼之後,接着會找查詢優化器(Optimizer)來選擇一個最優的查詢路徑。所以查詢優化器大概就是幹這個的,他會針對你編寫的幾十行、幾百行甚至上千行的複雜SQL語句生成查詢路徑樹,然後從裏面選擇一條最優的查詢路徑出來。相當於他會告訴你,你應該按照一個什麼樣的步驟和順序,去執行哪些操作,然後一步一步的把SQL語句就給完成了。

10. 執行器

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

11. 存儲引擎

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

12. 邏輯架構

現在把上述組件綜合起來看得到如下架構與流程圖。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章