架構(gòu)
// TODO 架構(gòu)圖
大體來(lái)說(shuō),MySQL分為 Server層 和 存儲(chǔ)引擎層 兩部分
Server層包括:連接器、查詢(xún)緩存、分析器、優(yōu)化器迂曲、執(zhí)行器。涵蓋MySQL大多數(shù)核心服務(wù)功能嫉沽,以及所有的內(nèi)置函數(shù)(時(shí)間呀潭、日期、數(shù)學(xué)降传、加密函數(shù)等)篷朵,所有跨存儲(chǔ)引擎的功能都在這一層實(shí)現(xiàn),比如存儲(chǔ)過(guò)程婆排、觸發(fā)器声旺、視圖等。
存儲(chǔ)引擎層:負(fù)責(zé)數(shù)據(jù)的存儲(chǔ)和讀取段只。其架構(gòu)模式是插件式的腮猖,支持InnoDB、MyISAM赞枕、Memory等引擎澈缺。
Server層
連接器
負(fù)責(zé)跟客戶端建立連接、獲取權(quán)限炕婶、維持和管理連接
查詢(xún)緩存
MySQL拿到一個(gè)查詢(xún)請(qǐng)求后姐赡,會(huì)先到查詢(xún)緩存看看,之前是不是執(zhí)行過(guò)這條語(yǔ)句柠掂。之前執(zhí)行過(guò)的語(yǔ)句及其結(jié)果會(huì)以 key-value 對(duì)的形式项滑,直接緩存在內(nèi)存中。key是查詢(xún)語(yǔ)句涯贞,value是查詢(xún)結(jié)果枪狂。
如果查詢(xún)能在緩存中找到key,則直接返回value給客戶端宋渔。如果找不到摘完,就會(huì)繼續(xù)后面的執(zhí)行階段,執(zhí)行完成后傻谁,執(zhí)行結(jié)果會(huì)被存入查詢(xún)緩存中孝治。
大多數(shù)情況下不要用查詢(xún)緩存,因?yàn)橥状笥诶?br> 查詢(xún)緩存的失效非常頻繁,只要有對(duì)一個(gè)表的更新谈飒,這個(gè)表上所有的查詢(xún)緩存都會(huì)被清空岂座。MySQL8.0版本,直接將查詢(xún)緩存功能整塊去掉了杭措。
分析器
如果沒(méi)有命中查詢(xún)緩存费什,就要開(kāi)始真正執(zhí)行語(yǔ)句了。首先MySQL需要知道要做什么手素,所以需要對(duì)SQL語(yǔ)句進(jìn)行解析鸳址。
先做詞法分析,識(shí)別語(yǔ)句中的字符串分別是什么泉懦、代表什么稿黍,識(shí)別出關(guān)鍵詞,表名崩哩、列等巡球。
再做語(yǔ)法分析,對(duì)詞法分析的結(jié)果邓嘹,根據(jù)語(yǔ)法規(guī)則酣栈,判斷SQL語(yǔ)句是否滿足MySQL語(yǔ)法。
優(yōu)化器
表里有多個(gè)索引的時(shí)候汹押,決定使用哪個(gè)索引矿筝;或者在一個(gè)語(yǔ)句有多表關(guān)聯(lián)的時(shí)候,決定各個(gè)表的連接順序棚贾。
執(zhí)行器
MySQL 通過(guò)分析器知道了你要做什么跋涣,通過(guò)優(yōu)化器知道了該怎么做,于是就進(jìn)入了執(zhí)行器階段鸟悴,開(kāi)始執(zhí)行語(yǔ)句陈辱。
開(kāi)始執(zhí)行的時(shí)候,要先判斷一下你對(duì)這個(gè)表T有沒(méi)有執(zhí)行查詢(xún)的權(quán)限细诸。
如果沒(méi)有沛贪,就會(huì)返回沒(méi)有權(quán)限的錯(cuò)誤(如果命中查詢(xún)緩存,會(huì)在查詢(xún)緩存返回結(jié)果的時(shí)候震贵,做權(quán)限驗(yàn)證利赋。查詢(xún)也會(huì)在優(yōu)化器之前調(diào)用precheck驗(yàn)證權(quán)限)
權(quán)限驗(yàn)證不僅會(huì)在執(zhí)行器這部分會(huì)做,在分析器之后猩系,也就是知道了該語(yǔ)句要干什么之后媚送,也會(huì)先做一次權(quán)限驗(yàn)證,叫做precheck寇甸,而precheck是無(wú)法對(duì)運(yùn)行時(shí)涉及到的表進(jìn)行權(quán)限驗(yàn)證的塘偎,比如使用了觸發(fā)器的情況疗涉。因此在執(zhí)行器這里也要做一次執(zhí)行時(shí)的權(quán)限驗(yàn)證。
如果有權(quán)限吟秩,就打開(kāi)表繼續(xù)執(zhí)行咱扣。執(zhí)行器會(huì)根據(jù)表的引擎定義,去使用這個(gè)引擎提供的接口涵防。
相關(guān)問(wèn)題
- 問(wèn):表T闹伪,沒(méi)有k字段,執(zhí)行下面語(yǔ)句時(shí)會(huì)報(bào)字段不存在的錯(cuò)誤壮池,這個(gè)錯(cuò)誤是在哪個(gè)階段報(bào)出來(lái)的呢偏瓤?
select * from T where k = 1;
答:分析器。
《高性能mysql》里提到解析器和預(yù)處理器椰憋。
解析器處理語(yǔ)法和解析查詢(xún)厅克,生成一棵對(duì)應(yīng)的解析樹(shù)。
預(yù)處理器進(jìn)一步檢查解析樹(shù)的合法熏矿,比如數(shù)據(jù)表已骇、數(shù)據(jù)列是否存在离钝,別名是否有歧義等票编。如果通過(guò)則生成新的解析樹(shù),提交給優(yōu)化器卵渴。
詞法解析慧域、語(yǔ)法解析、語(yǔ)義解析(在語(yǔ)義解析這步做)
- 問(wèn):對(duì)于表的操作權(quán)限驗(yàn)證在哪里進(jìn)行浪读?
答:查詢(xún)緩存昔榴、優(yōu)化器之前的precheck、執(zhí)行器
連接器從權(quán)限表里查詢(xún)用戶權(quán)限碘橘,并保存在變量里以供查詢(xún)緩存互订、分析器、執(zhí)行器在檢查權(quán)限的時(shí)候使用
- 問(wèn):為什么要在執(zhí)行器再次驗(yàn)證權(quán)限痘拆?
答:sql執(zhí)行過(guò)程中可能會(huì)有觸發(fā)器這種在運(yùn)行時(shí)才能確定的過(guò)程仰禽,分析器工作結(jié)束后的precheck是不能對(duì)這種運(yùn)行時(shí)涉及到的表進(jìn)行權(quán)限驗(yàn)證的,所以需要在執(zhí)行器階段進(jìn)行權(quán)限驗(yàn)證纺蛆。