MySQL可以分為
Server
層和存儲引擎
層兩部分
-
Server
層包括連接器拦键、查詢緩存、分析器檩淋、優(yōu)化器芬为、執(zhí)行器等,涵蓋MySQL的大多數(shù)核心服務功能蟀悦,以及所有的內(nèi)置函數(shù)(如日期碳柱、時間、數(shù)學和加密函數(shù)等)熬芜,所有跨存儲引擎的功能都在這一層實現(xiàn)莲镣,比如存儲過程、觸發(fā)器涎拉、視圖等瑞侮。 -
存儲引擎層
負責數(shù)據(jù)的存儲和提取的圆。其架構(gòu)模式是插件式的,支持InnoDB半火、MyISAM越妈、Memory等多個存儲引擎。現(xiàn)在最常用的存儲引擎是InnoDB钮糖,它從MySQL 5.5.5版本開始成為了默認存儲引擎梅掠。 - 不同的存儲引擎共用一個Server層,也就是從連接器到執(zhí)行器的部分
一條普通的查詢語是怎樣執(zhí)行并返回結(jié)果了
mysql> select * from table_test where id=10店归;
連接器
- 第一步阎抒,你會先連接到這個數(shù)據(jù)庫上,這時候接待你的就是連接器消痛。連接器負責跟客戶端建立連接且叁、獲取權限、維持和管理連接秩伞。連接完成后逞带,如果你沒有后續(xù)的動作,這個連接就處于空閑狀態(tài)纱新,你可以在
show processlist
命令中看到它展氓。客戶端如果太長時間沒動靜脸爱,連接器就會自動將它斷開遇汞。這個時間是由參數(shù)wait_timeout
控制的,默認值是8
小時阅羹。數(shù)據(jù)庫里面,長連接是指連接成功后教寂,如果客戶端持續(xù)有請求捏鱼,則一直使用同一個連接。短連接則是指每次執(zhí)行完很少的幾次查詢就斷開連接酪耕,下次查詢再重新建立一個导梆。
查詢緩存
- 連接建立完成后,你就可以執(zhí)行
select
語句了迂烁。執(zhí)行邏輯就會來到第二步:查詢緩存看尼。 - MySQL拿到一個查詢請求后,會先到查詢緩存看看盟步,之前是不是執(zhí)行過這條語句藏斩。之前執(zhí)行過的語句及其結(jié)果可能會以
key-value對
的形式,被直接緩存在內(nèi)存中却盘。key是查詢的語句
狰域,value是查詢的結(jié)果
媳拴。如果你的查詢能夠直接在這個緩存中找到key,那么這個value就會被直接返回給客戶端兆览。 - 如果語句不在查詢緩存中屈溉,就會繼續(xù)后面的執(zhí)行階段。執(zhí)行完成后抬探,執(zhí)行結(jié)果會被存入查詢緩存中子巾。
大多數(shù)情況下建議不要使用查詢緩存,查詢緩存往往弊大于利小压。查詢緩存的失效非常頻繁线梗,只要有對一個表的更新,這個表上所有的查詢緩存都會被清空场航。
分析器
- 如果沒有命中查詢緩存缠导,就要開始真正執(zhí)行語句了。首先溉痢,MySQL需要知道你要做什么僻造,因此需要對SQL語句做解析。分析器先會做
“詞法分析”
,詞法分析完后就要做“語法分析”
孩饼。根據(jù)詞法分析的結(jié)果髓削,語法分析器會根據(jù)語法規(guī)則,判斷你輸入的這個SQL語句是否滿足MySQL語法镀娶。如果你的語句不對立膛,就會收到“You have an error in your SQL syntax”
的錯誤提醒
優(yōu)化器
- 經(jīng)過了分析器,MySQL就知道你要做什么了梯码。在開始執(zhí)行之前宝泵,還要先經(jīng)過優(yōu)化器的處理。
- 優(yōu)化器是在表里面有多個索引的時候轩娶,決定使用哪個索引儿奶;或者在一個語句有多表關聯(lián)(join)的時候,決定各個表的連接順序鳄抒。
比如你執(zhí)行下面這樣的語句闯捎,這個語句是執(zhí)行兩個表的join:
mysql> select * from t1 join t2 using(ID) where t1.c=10 and t2.d=20;
- 既可以先從表t1里面 取出c=10的記錄的ID值,再根據(jù)ID值關聯(lián)到表t2许溅,再判斷t2里面d的值是否等于20瓤鼻。
- 也可以先從表t2里面取出d=20的記錄的ID值,再根據(jù)ID值關聯(lián)到t1贤重,再判斷t1里面c的值是否等于10茬祷。
這兩種執(zhí)行方法的邏輯結(jié)果是一樣的,但是執(zhí)行的效率會有不同并蝗,而優(yōu)化器的作用就是決定選擇使用哪一個方案牲迫。
執(zhí)行器
- MySQL通過分析器知道了你要做什么耐朴,通過優(yōu)化器知道了該怎么做,于是就進入了執(zhí)行器階段盹憎,開始執(zhí)行語句筛峭。
- 開始執(zhí)行的時候,要先判斷一下你對這個表T有沒有執(zhí)行查詢的權限陪每,如果沒有影晓,就會返回沒有權限的錯誤
- 如果有權限,就打開表繼續(xù)執(zhí)行檩禾。打開表的時候挂签,執(zhí)行器就會根據(jù)表的引擎定義,去使用這個引擎提供的接口盼产。
mysql> select * from T where ID=10;
比如我們這個例子中的表T中饵婆,ID字段沒有索引,那么執(zhí)行器的執(zhí)行流程是這樣的:
調(diào)用InnoDB引擎接口取這個表的第一行戏售,判斷ID值是不是10侨核,如果不是則跳過,如果是則將這行存在結(jié)果集中灌灾;
調(diào)用引擎接口取“下一行”搓译,重復相同的判斷邏輯,直到取到這個表的最后一行锋喜。
執(zhí)行器將上述遍歷過程中所有滿足條件的行組成的記錄集作為結(jié)果集返回給客戶端
- 至此些己,這個整個語句就執(zhí)行完成了。一條查詢語句的執(zhí)行過程一般是經(jīng)過連接器嘿般、分析器段标、優(yōu)化器、執(zhí)行器等功能模塊炉奴,最后到達存儲引擎逼庞。
參考:MySql實戰(zhàn)45講