MySQL 中一條 SQL 語句是如何執(zhí)行的?
MySQL執(zhí)行一條SQL語句,涉及到以下幾個(gè)過程:
客戶端連接
要執(zhí)行 SQL 語句,首先用戶需要通過客戶端連接到MySQL服務(wù)器,連接時(shí)需要指定用戶名和密碼,MySQL服務(wù)器中的連接器模塊會(huì)對(duì)用戶提供的用戶名和密碼進(jìn)行驗(yàn)證,并檢查用戶是否擁有執(zhí)行特定SQL語句的權(quán)限。一個(gè)用戶成功建立連接后,即使管理員對(duì)這個(gè)用戶的權(quán)限做了修改,也不會(huì)影響已經(jīng)存在連接的權(quán)限。修改完成后,只有新建的連接才會(huì)使用新的權(quán)限設(shè)置。
查詢緩存
如果執(zhí)行的是一條查詢語句,MySQL會(huì)先到查詢緩存中查找之前是不是執(zhí)行過這條語句,如果能在緩存中找到,就直接返回查詢結(jié)果。如果找不到,就繼續(xù)往下執(zhí)行。需要注意的是,如果一個(gè)表經(jīng)常更新,查詢緩存就會(huì)被頻繁清空,導(dǎo)致緩存的命中率非常低,所以MySQL 8.0 版本后,查詢緩存的功能被刪掉了。
解析SQL
在執(zhí)行某條SQL語句之前,MySQL需要先弄懂它的含義,所以需要解析器對(duì) SQL 語句做解析。解析器首先會(huì)對(duì)SQL語句進(jìn)行詞法分析,也就是將SQL語句字符串中的關(guān)鍵字識(shí)別出來,比如select,from等等。接著解析器再根據(jù)詞法分析的結(jié)果,對(duì)SQL語句進(jìn)行語法分析構(gòu)建出 SQL 語法樹,方便后面模塊獲取 SQL 類型、表名、字段名、 where 條件等等。
執(zhí)行SQL
在正式執(zhí)行SQL之前,還會(huì)經(jīng)過預(yù)處理和優(yōu)化兩個(gè)階段。預(yù)處理階段,預(yù)處理器會(huì)檢查 SQL 語句中的表或者字段是否存在。優(yōu)化階段,優(yōu)化器負(fù)責(zé)將SQL語句的執(zhí)行方案確定下來,比如在表里面有多個(gè)索引的時(shí)候,優(yōu)化器會(huì)基于查詢成本的考慮,來決定選擇使用哪個(gè)索引。
經(jīng)過優(yōu)化器確定執(zhí)行方案后,就由執(zhí)行器真正開始執(zhí)行SQL語句,執(zhí)行器通過API與存儲(chǔ)引擎交互,獲取數(shù)據(jù)或?qū)?shù)據(jù)進(jìn)行修改,并將執(zhí)行結(jié)果返回給用戶。
總的來說,MySQL執(zhí)行一條SQL語句,會(huì)經(jīng)過連接器處理客戶端連接、查詢緩存、解析器進(jìn)行詞法分析和語法分析生成語法樹、預(yù)處理器檢查表名和字段名、優(yōu)化器確定最優(yōu)執(zhí)行計(jì)劃以及最后執(zhí)行器與存儲(chǔ)引擎交互進(jìn)行數(shù)據(jù)操作等多個(gè)流程。