MySQL 基礎(chǔ)技術(shù)(一) —— MySQL 是如何查詢的坊谁?

之前,有一年多的工作客戶端領(lǐng)域的工作經(jīng)驗(yàn)滑臊。
后來口芍,也在字節(jié)做了一年多的后端業(yè)務(wù)。
現(xiàn)在希望做一些 MySQL 總結(jié)雇卷,豐富一下自己在后端領(lǐng)域的積累鬓椭。
目錄如下:
MySQL 基礎(chǔ)技術(shù)(一) —— MySQL 是如何查詢的颠猴?
MySQL 基礎(chǔ)技術(shù)(二) —— MySQL 是如何更新的?
MySQL 基礎(chǔ)技術(shù)(三)—— MySQL 如何保證數(shù)據(jù)不丟失小染?
MySQL 基礎(chǔ)技術(shù)(四)—— MySQL 如何保證高可用翘瓮?


一、引子

在日常工作中裤翩,我們執(zhí)行了一個(gè)簡(jiǎn)單的查詢語句:

select * from <table_name> where id = 647;

那么资盅,在 MySQL 內(nèi)部會(huì)如何工作呢?

二踊赠、架構(gòu)

首先呵扛,MySQL 架構(gòu)可以分為 Server層Engine層兩部分。

Server(服務(wù))層:

涵蓋了 MySQL 上層核心服務(wù)功能筐带。
包括 “連接器”今穿、“查詢緩存”、“分析器”伦籍、“優(yōu)化器”蓝晒、“執(zhí)行器”等等。
以及內(nèi)置功能函數(shù)(數(shù)學(xué)帖鸦、時(shí)間計(jì)算等等)芝薇,觸發(fā)器讼载、視圖等等跨存儲(chǔ)引擎的功能都在 Server 層實(shí)現(xiàn)鼻吮。

Engine(引擎)層:

主要負(fù)責(zé)數(shù)據(jù)的存儲(chǔ)和提取等底層服務(wù)眷蚓。
其實(shí)現(xiàn)是插件式的,MySQL 支持 InnoDB立倍、MyISAMMemory 等多個(gè)存儲(chǔ)引擎侣滩。
目前口注,最常用的是 InnoDB 存儲(chǔ)引擎。
而從 MySQL 5.5.5 版本開始君珠,InnoDB 成為了默認(rèn)存儲(chǔ)引擎寝志。

可以使用 show engines; 命令來查看各個(gè)引擎。

show engines;

幾個(gè)常用底層存儲(chǔ)引擎的簡(jiǎn)單區(qū)別:
InnoDB:支持事務(wù)策添,支持行鎖材部,支持外鍵。
MyISAM:不支持事務(wù)唯竹,只支持表鎖乐导,不支持外鍵。
Memory:所有數(shù)據(jù)置于內(nèi)存的存儲(chǔ)引擎浸颓,擁有極高的插入物臂,更新和查詢效率旺拉。但是會(huì)占用和數(shù)據(jù)量成正比的內(nèi)存空間。并且其內(nèi)容會(huì)在 MySQL 重新啟動(dòng)時(shí)丟失棵磷。


三蛾狗、架構(gòu)圖解

MySQL架構(gòu)

接下來我們依次解釋下各個(gè)組件:

1.連接器:

顧名思義,連接器負(fù)責(zé)跟客戶端建立連接仪媒、獲取權(quán)限沉桌、維持和管理鏈接的。

常用命令如下:

mysql -h$ip -P$port -u$user -p

在完成 TCP 握手后规丽,連接器會(huì)基于用戶名和密碼來驗(yàn)證身份蒲牧。
驗(yàn)證通過會(huì)查詢出當(dāng)前用戶的權(quán)限。
(這代表:即使修改了用戶權(quán)限赌莺,也只會(huì)影響下次連接時(shí)的權(quán)限冰抢。之前連接過的權(quán)限依然是舊的權(quán)限)

執(zhí)行 show processlist; 可以查詢當(dāng)前的連接狀態(tài)。

show processlist;

如果客戶端長(zhǎng)時(shí)間沒有操作艘狭,連接器會(huì)自動(dòng)斷開挎扰。這個(gè)時(shí)間是由 wait_timeout 控制的,默認(rèn)是8小時(shí)巢音。

2.查詢緩存

建立完連接之后遵倦,會(huì)優(yōu)先查詢有沒有緩存。
在打開查詢緩存的前提下官撼,
每次執(zhí)行過的 select 語句會(huì)以 Key - Value 的形式保存在內(nèi)存中梧躺。
如果緩存命中,就會(huì)直接返回結(jié)果給客戶端傲绣。

但是查詢緩存往往弊大于利掠哥,得看場(chǎng)景使用。

查詢緩存的失效非常頻繁秃诵,只要表有更新续搀,那么表上所有的查詢緩存都會(huì)被清空。
大大降低了查詢緩存的命中率菠净,還犧牲了MySQL的部分性能禁舷。
除非是一種更新頻率較低的靜態(tài)表,可以打開查詢緩存毅往。(可以用SQL_CACHE顯示制定牵咙。 如:select SQL_CACHE * from <table_name>)
更新頻率比較高的表建議不要使用查詢緩存。(query_cache_type 設(shè)置成 DEMAND)

注意:
MySQL 8.0 開始攀唯,已經(jīng)廢棄查詢緩存功能霜大。
因?yàn)榫彺胬鲜菚?huì)被 update/insert/delete 操作清除掉,緩存了還沒來得及用就又沒了革答。

3.分析器

詞法分析

首先战坤,會(huì)進(jìn)行詞法分析曙强。
將一個(gè)完整的SQL語句,拆分成語句類型(select? insert? update? ...)途茫、表名碟嘴、列名等等。

語法分析

其次囊卜,會(huì)進(jìn)行語法分析娜扇。
判斷 SQL 語句是否符合 MySQL 語法。
如果錯(cuò)誤栅组,會(huì)報(bào)出下面的錯(cuò)誤:
ou have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ...
這時(shí)雀瓢,我們只要修正 use near 后面的語句即可。

4.優(yōu)化器

上一步玉掸,分析器通過“詞法分析”刃麸、“語法分析”解析出這條 SQL 具體要做的事。
優(yōu)化器司浪,會(huì)基于這條 SQL 來分析具體要使用哪個(gè)索引方案泊业。

具體可以使用 explain <sql>; 命令來分析 MySQL 的索引選擇。
這個(gè)命令在優(yōu)化 MySQL 查詢效率時(shí)會(huì)經(jīng)常用到啊易。

例如:

explain select * from <table_name> where id = 647;

會(huì)分析出具體使用哪個(gè)索引方案吁伺,是否符合我們預(yù)期。
如果不符合我們的預(yù)期租谈,可以使用 force index 命令來強(qiáng)制使用某個(gè)索引篮奄。(絕大部分場(chǎng)景下,MySQL選擇的都是最優(yōu)的)

5.執(zhí)行器

分析器知道了 SQL 要做什么割去,
優(yōu)化器明確了 SQL 需要用哪個(gè)索引方案窟却。
執(zhí)行器才會(huì)真正的基于索引方案,開始執(zhí)行查詢語句劫拗。

執(zhí)行之前间校,會(huì)判斷一下當(dāng)前連接的用戶有無該表的權(quán)限矾克。
如果有權(quán)限页慷,就會(huì)根據(jù)表的 Engine 選擇來調(diào)用對(duì)應(yīng)的引擎接口。

舉例:
user_info 表的存儲(chǔ)引擎是 InnoDB胁附。

select * from user_info where name = "647";

如果 name 列沒有聲明任何索引酒繁,執(zhí)行步驟如下:

  1. 調(diào)用 innoDB 引擎接口獲取表的第一行,判斷 name 是否等于 647控妻。如果不是州袒,跳過。如果是弓候,將結(jié)果保存郎哭。
  2. 調(diào)用 innoDB 引擎接口獲取表的下一行他匪,重復(fù)相同邏輯,一直到表的最后一行夸研。
  3. 將所有滿足條件的結(jié)果集返回給客戶端邦蜜。

如果 name 列有索引,執(zhí)行步驟如下:

  1. 調(diào)用 innoDB 引擎接口獲取索引樹(B+樹)亥至,基于索引樹快速查到 name 等于 647 的所有主鍵id悼沈。
  2. 將所有滿足條件的組件 id,回主表查詳細(xì)信息姐扮。(這個(gè)操作稱為“回表”)
  3. 將所有滿足條件的結(jié)果集返回給客戶端絮供。

參考與致謝:
1.《MySQL實(shí)戰(zhàn)45講》(林曉斌老師)
2.《MySQL存儲(chǔ)引擎對(duì)比》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市茶敏,隨后出現(xiàn)的幾起案子壤靶,更是在濱河造成了極大的恐慌,老刑警劉巖睡榆,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萍肆,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡胀屿,警方通過查閱死者的電腦和手機(jī)塘揣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宿崭,“玉大人亲铡,你說我怎么就攤上這事∑隙遥” “怎么了奖蔓?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)讹堤。 經(jīng)常有香客問我吆鹤,道長(zhǎng),這世上最難降的妖魔是什么洲守? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任疑务,我火速辦了婚禮,結(jié)果婚禮上梗醇,老公的妹妹穿的比我還像新娘知允。我一直安慰自己,他們只是感情好叙谨,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布温鸽。 她就那樣靜靜地躺著,像睡著了一般手负。 火紅的嫁衣襯著肌膚如雪涤垫。 梳的紋絲不亂的頭發(fā)上姑尺,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音蝠猬,去河邊找鬼股缸。 笑死,一個(gè)胖子當(dāng)著我的面吹牛吱雏,可吹牛的內(nèi)容都是我干的敦姻。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼歧杏,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼镰惦!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起犬绒,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤旺入,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后凯力,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體茵瘾,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年咐鹤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拗秘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡祈惶,死狀恐怖雕旨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情捧请,我是刑警寧澤凡涩,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站疹蛉,受9級(jí)特大地震影響活箕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜可款,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一育韩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧筑舅,春花似錦座慰、人聲如沸陨舱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽游盲。三九已至误墓,卻和暖如春蛮粮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谜慌。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工然想, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人欣范。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓变泄,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親恼琼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子妨蛹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

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