深刻學習MySQL,從概覽MySQL邏輯架構開始。mysql
首先來看一下MySQL的邏輯架構圖:sql
MySQL邏輯架構大概能夠分爲三層:數據庫
值得一提的是在MySQL8.0中取消了查詢緩存,大概的理由是查詢緩存存在嚴重的可伸縮性問題,而且很容易成爲嚴重的瓶頸緩存,將緩存移動到客戶端能收穫更好的性能。緩存
經過一條查詢語句的執行過程,來了解一些關鍵的部件:安全
mysql> select * from T where ID=10;
首先,須要鏈接數據庫。服務器
當客戶端(應用)鏈接到MySQL服務器時,服務器須要對其進行認證。認證基於用戶名、原始主機信息和密碼。網絡
鏈接命令:架構
mysql -h$ip -P$port -u$user -p
除了基本認證以外,鏈接器還會進行一些線程的處理。函數
每一個客戶端鏈接都會在服務器進程中擁有一個線程,這個鏈接的查詢只會在這個單獨的線程中執行,該線程只能輪流在某個CPU核心或者CPU中運行。服務器會負責緩存線程,所以不須要爲每個新建的鏈接建立或者銷燬線程。工具
對於SELECT語句,在解析查詢以前,服務器會先檢查查詢緩存(Query Cache),若是可以在其中找到對應的查詢,服務器就沒必要再執行查詢解析、優化和執行的整個過程,而是直接返回查詢緩存中的結果集。
但不推薦使用查詢緩存,爲何呢?由於查詢緩存每每弊大於利。
查詢緩存的失效很是頻繁,只要有對一個表的更新,這個表上全部的查詢緩存都會被清空。對於更新壓力大的數據庫來講,查詢緩存的命中率會很是低。除非你的業務就是有一張靜態表,很長時間纔會更新一次。好比,一個系統配置表,那這張表上的查詢才適合使用查詢緩存。
好在MySQL也提供了這種「按需使用」的方式。能夠將參數query_cache_type設置成DEMAND,這樣對於默認的SQL語句都不使用查詢緩存。而對於肯定要使用查詢緩存的語句,能夠用SQL_CACHE顯式指定,以下:
mysql> select SQL_CACHE * from T where ID=10;
上面也提到了MySQL8.0完全廢棄了查詢緩存的功能。
若是緩存沒有命中的話,MySQL會對查詢語句進行解析。簡單說解析的做用將咱們人能看懂的SQL解析成MySQ能識別的語言。
解析器先會作「詞法解析」。輸入的是由多個字符串和空格組成的一條SQL語句,MySQL須要識別出裏面的字符串分別是什麼,表明什麼。
MySQL從輸入的"select"這個關鍵字識別出來,這是一個查詢語句。它也要把字符串「T」識別成「表名T」,把字符串「ID」識別成「列ID」。
作完了這些識別之後,就要作「語法解析」。根據詞法解析的結果,語法解析器會根據語法規則,判斷輸入的這個SQL語句是否知足MySQL語法。
通過了解析器器,MySQL知道咱們要幹什麼。
接下來並非直接執行,而是會在優化器這一層進行優化,優化器是個很是複雜的部件,它會幫我去使用他本身認爲的最好的方式去優化這條 SQL 語句,並生成一條條的執行計劃。
例如在表裏面有多個索引的時候,決定使用哪一個索引;或者在一個語句有多表關聯(join)的時候,決定各個表的鏈接順序。好比你執行下面這樣的語句,這個語句是執行兩個表的join:
mysql> select * from t1 join t2 using(ID) where t1.c=10 and t2.d=20;
這兩種執行方法的邏輯結果是同樣的,可是執行的效率會有不一樣,而優化器的做用就是決定選擇使用哪個方案。
優化器階段完成後,這個語句的執行方案就肯定下來了,而後進入執行器階段。若是你還有一些疑問,好比優化器是怎麼選擇索引的,有沒有可能選擇錯等等,不要緊,我會在後面的文章中單獨展開說明優化器的內容。
MySQL經過解析器知道了你要作什麼,經過優化器知道了該怎麼作,因而就進入了執行器階段,執行器會根據一系列的執行計劃去調用存儲引擎的接口去完成SQL的執行。
開始執行的時候,要先判斷一下你對這個表T有沒有執行查詢的權限,若是沒有,就會返回沒有權限的錯誤,以下所示(在工程實現上,若是命中查詢緩存,會在查詢緩存放回結果的時候,作權限驗證。查詢也會在優化器以前調用precheck驗證權限)。
mysql> select * from T where ID=10; ERROR 1142 (42000): SELECT command denied to user 'b'@'localhost' for table 'T'
若是有權限,就打開表繼續執行。打開表的時候,執行器就會根據表的引擎定義,去使用這個引擎提供的接口。
好比咱們這個例子中的表T中,ID字段沒有索引,那麼執行器的執行流程是這樣的:
至此,這個語句就執行完成了。
對於有索引的表,執行的邏輯也差很少。第一次調用的是「取知足條件的第一行」這個接口,以後循環取「知足條件的下一行」這個接口,這些接口都是引擎中已經定義好的。
參考:
【1】:《高性能MySQL》
【2】:極客時間 《MySQL實戰45講》
【3】:《MySQL技術內幕 InnoDB存儲引擎》