一邀泉、架構(gòu)
在討論MySQL前其徙,一條SQL語句是怎樣執(zhí)行之前胚迫,我們首先了解下MySQL中有那些組件。
大體來說唾那,MySQL 可以分為 Server層和存儲引擎層兩部分访锻。
Server層包括連接器、查詢緩存、分析器朗若、優(yōu)化器恼五、執(zhí)行器等昌罩,涵蓋 MySQL 的大多數(shù)核心服務(wù)功能哭懈,以及所有的內(nèi)置函數(shù)(如日期、時(shí)間茎用、數(shù)學(xué)和加密函數(shù)等)遣总,所有跨存儲引擎的功能都在這一層實(shí)現(xiàn),比如存儲過程轨功、觸發(fā)器旭斥、視圖等。
存儲引擎層負(fù)責(zé)數(shù)據(jù)的存儲和提取古涧。其架構(gòu)模式是插件式的垂券,支持 InnoDB、MyISAM羡滑、Memory 等多個(gè)存儲引擎」阶Γ現(xiàn)在最常用的存儲引擎是 InnoDB,它從 MySQL 5.5.5 版本開始成為了默認(rèn)存儲引擎柒昏。不同的存儲引擎共用一個(gè)Server 層凳宙。
二、組件
連接器
首先职祷,客戶端要連接上數(shù)據(jù)庫氏涩,這時(shí)由連接器來進(jìn)行建立連接、獲取權(quán)限有梆、維持和管理連接是尖。
通過客戶端工具和服務(wù)端建立連接,完成經(jīng)典的TCP握手泥耀,連接器就開始認(rèn)證身份了饺汹,如果認(rèn)證通過,連接器會在權(quán)限表中查出當(dāng)前賬號擁有的權(quán)限爆袍,之后這個(gè)連接里面的權(quán)限判斷邏輯首繁,都將依賴于此時(shí)讀到的權(quán)限。
連接完成后陨囊,如果你沒有后續(xù)的動作弦疮,這個(gè)連接就處于空閑狀態(tài)≈┐祝客戶端如果太長時(shí)間沒動靜胁塞,連接器就會自動將它斷開。這個(gè)時(shí)間是由參數(shù) wait_timeout 控制的,默認(rèn)值是 8 小時(shí)啸罢。
查詢緩存
連接建立完成后编检,你就可以執(zhí)行 select 語句了。執(zhí)行邏輯就會來到第二步:查詢緩存扰才。
MySQL 拿到一個(gè)查詢請求后允懂,會先到查詢緩存看看,之前是不是執(zhí)行過這條語句衩匣。之前執(zhí)行過的語句及其結(jié)果可能會以 key-value 對的形式蕾总,被直接緩存在內(nèi)存中。如果查詢時(shí)命中琅捏,則會直接將對應(yīng)的v返回給客戶端生百,如果語句不在查詢緩存中,就會繼續(xù)后面的執(zhí)行階段柄延。執(zhí)行完成后蚀浆,執(zhí)行結(jié)果會被存入查詢緩存中。
但是搜吧,查詢緩存的失效是很容易的市俊,只要對表進(jìn)行了修改,這張表上的緩存都會被清空赎败,這樣設(shè)計(jì)避免了查詢到臟數(shù)據(jù)秕衙。但也造成緩存命中率非常低,MySQL 8.0及之后就刪除了這塊功能了僵刮。
分析器
如果沒有命中查詢緩存据忘,就要開始真正執(zhí)行語句了。首先搞糕,MySQL 需要知道你要做什么勇吊,因此需要對 SQL 語句做解析。
分析器先會做“詞法分析”窍仰。你輸入的是由多個(gè)字符串和空格組成的一條 SQL 語句汉规,MySQL 需要識別出里面的字符串分別是什么,代表什么驹吮。
之后针史,就要做“語法分析”。根據(jù)詞法分析的結(jié)果碟狞,語法分析器會根據(jù)語法規(guī)則啄枕,判斷你輸入的這個(gè) SQL 語句是否滿足 MySQL 語法。
優(yōu)化器
經(jīng)過了分析器族沃,MySQL 就知道你要做什么了频祝。在開始執(zhí)行之前泌参,還要先經(jīng)過優(yōu)化器的處理。
優(yōu)化器是在表里面有多個(gè)索引的時(shí)候常空,決定使用哪個(gè)索引沽一;或者在一個(gè)語句有多表關(guān)聯(lián)(join)的時(shí)候,決定各個(gè)表的連接順序漓糙。
執(zhí)行器
MySQL 通過分析器知道了你要做什么铣缠,通過優(yōu)化器知道了該怎么做,于是就進(jìn)入了執(zhí)行器階段兼蜈,開始執(zhí)行語句攘残。
開始執(zhí)行的時(shí)候拙友,要先判斷一下你對這個(gè)表有沒有執(zhí)行查詢的權(quán)限为狸,如果沒有,就會返回沒有權(quán)限的錯(cuò)誤遗契。
如果有權(quán)限辐棒,就打開表繼續(xù)執(zhí)行。打開表的時(shí)候牍蜂,執(zhí)行器就會根據(jù)表的引擎定義漾根,去使用這個(gè)引擎提供的接口將結(jié)果集返回給客戶端。