面試官:說說一條查詢sql的執(zhí)行流程和底層原理椿浓?

作者:孤獨煙太援,資深后端工程師,業(yè)內(nèi)知名原創(chuàng)作者

一條查詢SQL執(zhí)行流程圖如下

img

本文改編自《高性能Mysql》扳碍,煙哥用小說的形式來講這個內(nèi)容提岔。

序章 自我介紹

我是一條sql,就是一條長長的字符串笋敞,不要問我長什么樣碱蒙,因為我比較傲嬌。

img

額~~不是我不說啊夯巷,因為細(xì)說起來赛惩,我可以細(xì)分為

DML

(Update、Insert趁餐、Delete),

DDL

(表結(jié)構(gòu)修改),

DCL

(權(quán)限操作),

DQL

(Select)操作,一個個去介紹喷兼,我怕大家嫌我煩!

嗯后雷,大家沒什么意見季惯,我繼續(xù)往下自我介紹了~

由于種類太多,這里我只是一條查詢SQL臀突,也就是一句DQL勉抓。

客戶端按照Mysql通信協(xié)議,把我發(fā)送到服務(wù)端候学。

當(dāng)我到達(dá)服務(wù)端后藕筋,我會在一個單獨的

線程

里進(jìn)行執(zhí)行。服務(wù)端要先…

img

萬萬沒想到盒齿,我又被打斷了~好吧念逞,因為我在一個線程里執(zhí)行困食,總要有辦法能看到線程的執(zhí)行狀態(tài)吧。Mysql提供了下面的命令翎承,給大家查看

SHOW [FULL] PROCESSLIST

出來的結(jié)果是長下面這樣的

img

圖里

Command

這一列硕盹,反應(yīng)的就是這個線程當(dāng)前的執(zhí)行狀態(tài)啦。我在這個線程的執(zhí)行過程中叨咖,狀態(tài)是會變化很多次瘩例。

你看圖里,有一個

Sleep

甸各,這是在告訴你線程正在等待客戶端發(fā)送新的請求垛贤。還有一個為

Query

,這代表線程正在執(zhí)行查詢或者正在將結(jié)果發(fā)送給客戶端。

至于其他的趣倾,還有

Locked
Sending data

等等聘惦,分別代表…

img

額,好吧儒恋,嘮嘮叨叨了一大堆善绎,大家居然木有嫌我煩,嗯诫尽,至于其他狀態(tài)的含義大家可以去Mysql官網(wǎng)查詢哦禀酱。

嗯,回到剛才的話題牧嫉。我到達(dá)服務(wù)端后剂跟,Mysql要判斷我的前6個字符是否為

select

。并且酣藻,語句中不帶有

SQL_NO_CACHE

關(guān)鍵字曹洽,如果符合條件,就進(jìn)入查詢緩存臊恋。

第一章 我和查詢緩存的那些事

說到查詢緩存衣洁,它其實是一個哈希表,它將執(zhí)行過的語句及其結(jié)果會以 key-value 對的形式抖仅,被直接緩存在內(nèi)存中坊夫。
它的key是一個哈希值,是通過查詢SQL(也就是我)撤卢、當(dāng)前要查詢的數(shù)據(jù)庫环凿、客戶端協(xié)議版本等,生成的一個哈希值放吩,而它的value自然就是查詢結(jié)果啦智听。

當(dāng)然,如果我要繞過查詢緩存,也很簡單到推。我可以像下面這么寫:

Select SQL_NO_CACHE * from table

也可以將參數(shù)query_cache_type設(shè)置成DEMAND來繞過查詢緩存考赛。

可是,有一天查詢緩存悲傷的對我說:"你將來再也看不到我了莉测,我已經(jīng)被歷史淘汰了颜骤,Mysql8.0版本開始就沒有我了!"
聽到這個消息后捣卤,我表面上故作堅強(qiáng)的對查詢緩存說:"不要方忍抽,大家會想你的!"
然而董朝,實際上心里想的是:"嘿嘿嘿鸠项,你個坑爹的,終于不存在了子姜!"大家不要覺得我太邪惡祟绊,畢竟查詢緩存實在是太不好用了。接下來我們來說說解析器…

img

萬萬沒想到闲询,本來想糊弄過去的久免。結(jié)果…好吧,回到正題扭弧,因為

  • 只要有對一個表的更新,這個表上所有的查詢緩存都會被清空
  • SQL任何字符上的不同,如空格,注釋,都會導(dǎo)致緩存不命中

因此记舆,我能想到用查詢緩存的表鸽捻,只有一種情況,那就是配置表泽腮。其他的業(yè)務(wù)表御蒲,根本是無法利用查詢緩存的特性,或許Mysql團(tuán)隊也是覺得查詢緩存的使用場景過于局限诊赊,就無情的將它剔除厚满。

第二章 我和分析器的愛恨情仇

(本文將解析器和預(yù)處理器統(tǒng)一稱為分析器)
話說,我離開查詢緩存后碧磅,進(jìn)入解析器碘箍。
解析器:"來來來,我先對你進(jìn)行詞法分析鲸郊,告訴我你長啥樣丰榴?"
我是下面這樣的

select username from userinfo

解析器:"好,好秆撮,好四濒。我有兩個階段,我先對你進(jìn)行詞法分析,我將你從左到右一個字符盗蟆、一個字符地輸入戈二,然后根據(jù)構(gòu)詞規(guī)則識別單詞。你將會生成4個Token,如下所示喳资。"

img

解析器:"接下來呢觉吭,進(jìn)行語法解析,判斷你輸入的這個 SQL 語句是否滿足 MySQL 語法骨饿。然后生成下面這樣一顆語法樹亏栈。"

img

我:"如果語法不對呢?"

解析器:"那你會收到一個提示如下宏赘!"

You have an error in your SQL syntax

解析器:"順利生成語法樹以后绒北,我就將你送往預(yù)處理器!"
預(yù)處理器:"老弟察署,你來拉!"
我:"嗯闷游!"
預(yù)處理器:"老弟,我來幫你看看你的列名對不對贴汪,數(shù)據(jù)庫的這張表里是不是真的有這個列脐往。再看看表名對不對,如果不對扳埂,你會看到下面的錯誤业簿!"

Unknown column xxx in ‘where clause’

預(yù)處理器:"最后我再給你送去做權(quán)限驗證,如果你沒有操作這個表的權(quán)限阳懂,會報下面這個錯誤!"

ERROR 1142 (42000): SELECT command denied to user 'root'@'localhost' for table 'xxx'

(這個地方梅尤,大家可能有疑問,因為有些文章說是執(zhí)行器做的權(quán)限驗證岩调,可以直接拉到本文底部看說明)

最后巷燥,這顆語法樹會傳遞給優(yōu)化器。

第三章 我和優(yōu)化器的動人過往

在告別了解析器后号枕,我進(jìn)入了優(yōu)化器缰揪。
優(yōu)化器大哥:"告訴我,你長什么樣按写尽钝腺?"
我說道:"大哥不要捉急,我是長這樣的~"(這里優(yōu)化的其實應(yīng)該是語法樹蛙紫,我只是為了便于說明拍屑,才用SQL當(dāng)例子,實際上是針對語法樹進(jìn)行優(yōu)化)

select t1.*
from Table1 t1
inner join Table2 t2
on t1.CommonID = t2.CommonID

優(yōu)化器大哥:"我的任務(wù)就是幫你判斷一下怎么樣執(zhí)行更快坑傅,比如先查Table1再查Table2僵驰,還是先查Table2再查Table1呢?判斷完如何執(zhí)行以后,生成執(zhí)行計劃就好啦蒜茴!"
我很不信任的說道:“哼星爪,你就不會判斷失誤么!”
優(yōu)化器大哥:"那就要對SQL進(jìn)行改寫啦粉私,比如你帶了STRAIGHT_JOIN關(guān)鍵字顽腾,長下面這樣"

select t1.*
from Table1 t1
STRAIGHT_JOIN  Table2 t2
on t1.CommonID = t2.CommonID

"那我就知道強(qiáng)制先找Table1再關(guān)聯(lián)找Table2啦,類似的例子還有很多诺核,我就不一一列舉了抄肖!"
(STRAIGHT_JOIN功能同join類似,但能讓左邊的表來驅(qū)動右邊的表窖杀,能改表優(yōu)化器對于聯(lián)表查詢的執(zhí)行順序漓摩。)

我說道:"哇塞,如何編寫一個高效的SQL入客,真是一門學(xué)問肮鼙小!"
于是桌硫,優(yōu)化器大哥將我變身為一個執(zhí)行計劃夭咬,然后交給執(zhí)行器啦~

第四章 我和執(zhí)行器的悲情經(jīng)歷

我:"執(zhí)行器大哥,你是用來做什么的铆隘?"
執(zhí)行器:"就是根據(jù)執(zhí)行計劃來進(jìn)行執(zhí)行查詢啦卓舵。我就根據(jù)你的指令,逐條調(diào)用底層存儲引擎膀钠,逐步執(zhí)行边器。"
MySQL定義了一系列抽象存儲引擎API,以支持插件式存儲引擎架構(gòu)托修。Mysql實現(xiàn)了一個抽象接口層,叫做 handler(sql/handler.h)恒界,其中定義了接口函數(shù)睦刃,比如:ha_open, ha_index_end, ha_create等等,存儲引擎需要實現(xiàn)這些接口才能被系統(tǒng)使用十酣。

末章 一些感慨

最后一個階段涩拙,Mysql會將查詢結(jié)果返回客戶端。
唯一需要說明的是耸采,如果是SELECT類型的SQL兴泥,Mysql會將查詢結(jié)果緩存起來。至于其他的SQL虾宇,就將該表涉及到的查詢緩存清空搓彻。

一些疑問

這里關(guān)于權(quán)限驗證究竟在哪個階段執(zhí)行,大家可能會有一些疑問。
之前有一個大牛的文章說是權(quán)限驗證是在執(zhí)行階段旭贬,去執(zhí)行前驗證權(quán)限怔接,大家如果看過他的文章,可能會有疑問稀轨。我也不是亂質(zhì)疑人家扼脐,畢竟我只是一個小咖。我在這里只是發(fā)表一下我自己的論點奋刽,歡迎大家拍磚瓦侮。

論點一:權(quán)限驗證在執(zhí)行器中判斷從邏輯上說不通
一條查詢SQL經(jīng)過查詢緩存、分析器佣谐、優(yōu)化器肚吏,執(zhí)行器。如果到最后一個階段執(zhí)行器中才發(fā)現(xiàn)權(quán)限不足台谍、那不是前面一系列流程白做了须喂,Mysql應(yīng)該不至于這么傻吧~

論點二:同《高性能Mysql》一書內(nèi)容不符
該書209頁有一句話如下圖所示

img

該書也指明權(quán)限驗證是在預(yù)處理器中執(zhí)行。本文中將預(yù)處理和解析器統(tǒng)一劃分為分析器的范疇趁蕊。

論點三:同源碼不符
我翻看了Mysql5.7.25這個版本的源碼坞生,其在處理查詢這段的核心代碼如下
sql_parse.cc文件中,有這么一段代碼如下

case SQLCOM_SELECT:
 {
    //省略
    res= select_precheck(thd, lex, all_tables, first_table);
    if (!res)
      res= execute_sqlcom_select(thd, all_tables);
    //省略
  }

其中select_precheck是進(jìn)行權(quán)限校驗掷伙。而優(yōu)化器和執(zhí)行器是在execute_sqlcom_select這個方法中是己。
當(dāng)然,大家有新的見解任柜,歡迎留言卒废。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市宙地,隨后出現(xiàn)的幾起案子摔认,更是在濱河造成了極大的恐慌,老刑警劉巖宅粥,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件参袱,死亡現(xiàn)場離奇詭異,居然都是意外死亡秽梅,警方通過查閱死者的電腦和手機(jī)抹蚀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來企垦,“玉大人环壤,你說我怎么就攤上這事〕睿” “怎么了郑现?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵湃崩,是天一觀的道長。 經(jīng)常有香客問我懂酱,道長竹习,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任列牺,我火速辦了婚禮整陌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瞎领。我一直安慰自己泌辫,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布九默。 她就那樣靜靜地躺著震放,像睡著了一般。 火紅的嫁衣襯著肌膚如雪驼修。 梳的紋絲不亂的頭發(fā)上殿遂,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天,我揣著相機(jī)與錄音乙各,去河邊找鬼墨礁。 笑死,一個胖子當(dāng)著我的面吹牛耳峦,可吹牛的內(nèi)容都是我干的恩静。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蹲坷,長吁一口氣:“原來是場噩夢啊……” “哼驶乾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起循签,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤级乐,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后县匠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體唇牧,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年聚唐,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片腔召。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡杆查,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出臀蛛,到底是詐尸還是另有隱情亲桦,我是刑警寧澤崖蜜,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站客峭,受9級特大地震影響豫领,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜舔琅,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一等恐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧备蚓,春花似錦课蔬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至流昏,卻和暖如春扎即,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背况凉。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工谚鄙, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人茎刚。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓襟锐,卻偏偏與公主長得像,于是被迫代替她去往敵國和親膛锭。 傳聞我的和親對象是個殘疾皇子粮坞,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內(nèi)容