1. 程式人生 > MYSQL進階教學 ><p>MySQL 邏輯架構</p>

<p>MySQL 邏輯架構</p>

從整體架構切入MySQL的學習,可以對 MySQL 有一個整體的把握,鳥瞰全貌,不至於一下陷入細節裡邊, 對於以後深入理解 MySQL 也是有很大幫助的。本文通過講解一條查詢語句在 MySQL 內部的執行過程,讓您對 MySQL 邏輯架構有更深的瞭解。

1. 邏輯架構組成

圖片描述上方是 MySQL 邏輯架構的簡單示意圖,總的來說,MySQL 包含 Server 層和儲存引擎層兩大部分。

Server 層包括連線池、查詢快取、解析器、優化器、執行器等,MySQL 的核心服務都在這一層。

儲存引擎層負責資料的儲存和提取,MySQL 採用外掛式的儲存引擎,常見的儲存引擎有 InnoDB、MyISAM、 CSV 等。其中 InnoDB 是最常用的儲存引擎,也是 MySQL 的預設儲存引擎(從5.5.5版本開始)。

2. 一條查詢語句是如何執行的

上一小節介紹了 MySQL 的邏輯架構組成,那麼各模組之間是如何協同工作的呢?這裡以一條最簡單的查詢語句為例子,我們一起來看看這條語句在 MySQL 內部是如何執行的。

select id from a where id=1;

2.1 連線池

首先,我們通過 mysql 這個客戶端工具進行資料庫的連線,這時遇到的是連線池。連線池負責客戶端的連線管理、授權認證。

連線命令如下(輸入完連線命令後,需要輸入使用者密碼):

mysql -h localhost -u root -p
  • 如果使用者名稱和密碼認證通過,連線池會通過許可權表獲取這個使用者名稱所擁有的許可權資訊;

  • 如果使用者名稱或密碼認證不通過,則會收到一個錯誤提示:“ERROR 1045 (28000): Access denied for user ‘root’@‘localhost’”;

建立連線後,會產生相應的連線資訊,可以通過 show processlist 命令檢視。下方圖中 Id 為 5048 這一行,即為成功連線資料庫所建立的連線資訊,請注意 Command 這一列,值為”Sleep“,表明這是一個空閒連線。成功連線資料庫後,如果沒有任何動作,這個連線就會變成空閒狀態。

root@localhost [(none)]>show processlist;
+------+------+-----------+------+---------+------+----------+------------------+
| Id | User | Host | db | Command | Time | State | Info | +------+------+-----------+------+---------+------+----------+------------------+ | 4771 | root | localhost | NULL | Query | 0 | starting | show processlist | | 5048 | root | localhost | NULL | Sleep | 3 | | NULL | +------+------+-----------+------+---------+------+----------+------------------+ 2 rows in set (0.00 sec)

2.2 查詢快取

連線成功建立後,來到第二步查詢快取。查詢快取負責將執行過的語句和結果快取在記憶體中。

在獲取一個查詢請求後,MySQL會先到查詢快取進行檢視

  • 如果select語句在查詢快取中能夠找到,則直接返回結果給客戶端,跳過解析、優化、執行階段。
  • 如果select語句沒能在查詢快取中找到,則繼續後面的解析、優化、執行階段。

從這裡可以看到,如果命中查詢快取,MySQL 會直接返回結果給客戶端,後面的一系列操作不需要再執行,是非常高效的。但實際情況並非如此,查詢快取非常容易失效

因為只要一個表有更新操作,那這個表所有的查詢快取都會被清空。對一個承載正常業務的資料庫來說,更新操作是非常頻繁的,這就意味著查詢快取經常失效,從而導致查詢快取的命中率非常低。所以,使用查詢快取反而會給資料庫帶來額外的負擔,在實際生產環境中,我們建議關閉查詢快取

關閉查詢快取的方法有兩種:

  • 臨時:在 MySQL 中直接用命令列執行;

    set global query_cache_size=0
    set global query_cache_type=0
    
  • 永久:將以下兩個引數新增至配置檔案 my.cnf,並重啟 MySQL;

    query_cache_type=0
    query_cache_size=0
    

2.3 解析器

如果沒有命中查詢快取,接下來就要進入解析器階段了。解析器負責詞法解析和語法解析。

首先是詞法解析,MySQL 需要識別所輸入的字串分別代表什麼,它會從左到右一個字元、一個字元地輸入,然後根據構詞規則識別單詞。

select id from a where id=1;
關鍵字 非關鍵字 關鍵字 非關鍵字 關鍵字 非關鍵字
select 欄位id from 表名a where 欄位id等於1

接下來是語法解析,判斷輸入的這個SQL語句是否符合MySQL語法規則。如果語法不對,會收到錯誤資訊提示:“ERROR 1064 (42000): You have an error in your SQL syntax;”。如下面這個SQL語句的where少了一個e。

root@localhost [tempdb]>select id from a wher id=1;
ERROR 1064 (42000): 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 'id=1' at line 1

2.4 優化器

從解析器出來,就到了優化器階段。優化器負責找到最優的執行計劃,也就是決定SQL語句的執行方案。

一條查詢可以有很多種執行方式,最後都返回相同的結果 。比如下面這個查詢SQL,查詢表a中欄位id等於1的值

select id from a where id=1;
  • 可以遍歷表a所有行,找出所有id等於1的值
  • 也可以通過索引idx_id,找到id等於1的值。當然,前提是欄位id有建立索引idx_id。

兩種方案的結果是一樣的,但是執行效率不一樣,優化器的作用就是選擇最優的執行方案。

2.5 執行器

現在到了執行SQL語句的階段,也就是執行器。執行器負責呼叫儲存引擎,拿到查詢結果。

select id from a where id=1;

假設這個例子中的欄位id沒有索引,執行器的流程大致如下:

  1. 呼叫 InnoDB 引擎介面獲取表 a 的第一行,如果 id 值等於 1,則將 id 值存進結果集,如果 id 值不等於 1,則跳過,取下一行;
  2. 呼叫 InnoDB 引擎介面獲取下一行,重複第一步的邏輯,一直到表 a 的最後一行;
  3. 將符合查詢條件的結果集返回給客戶端。

3. 小結

一條 SQL 查詢的過程,大致就是這樣的流程:連線池、查詢快取、解析器、優化器、執行器。

連線池負責連線管理,查詢快取建議關閉,解析器讓 MySQL 知道要做什麼,優化器讓 MySQL 知道怎麼做,執行器負責執行取數。

通過本文的講解,對您認識 MySQL 邏輯架構,有所幫助嗎?歡迎反饋寶貴意見,以便我們不斷改進。