MySQL實(shí)戰(zhàn) -1 基本架構(gòu):

1、基本架構(gòu):一條SQL語(yǔ)句查詢(xún)語(yǔ)句是如何執(zhí)行?

下面介紹一下MySQL的基本架構(gòu)示意圖拓哟。

MySQL的邏輯架構(gòu)圖

MySQL 可以分為Server層和存儲(chǔ)引擎層兩個(gè)部分几缭。

1 河泳、客戶(hù)端
用來(lái)跟連接器建立連接的應(yīng)用程序。
2 年栓、 Server層

  • 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等多個(gè)存儲(chǔ)引擎迫淹。從MySQL5.5.5版本以后InnoDB為默認(rèn)存儲(chǔ)引擎秘通。你在create table 建表時(shí),若不指定引擎類(lèi)型敛熬,默認(rèn)就是InnoDB引擎肺稀。若想指定存儲(chǔ)引擎,通過(guò)engine=memory 方式指定应民。不同的存儲(chǔ)引擎卻共用一個(gè)Server層 话原,它是從連接器到執(zhí)行器的部分。
    3 诲锹、連接器
    你連接數(shù)據(jù)庫(kù)就需要通過(guò)連接器繁仁,與客戶(hù)端建立連接、獲取權(quán)限
    權(quán)限归园、維持和管理連接黄虱。
    eg.1

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

輸完命令之后,你就需要輸入密碼就可以登錄庸诱,也可以在p參數(shù)后直接跟密碼捻浦,但這樣你就想密碼暴露了,所有不建議這么做桥爽。
連接命令行中mysql就是客戶(hù)端工具朱灿,用來(lái)跟服務(wù)器建立連接。在完成經(jīng)典TCP握手后钠四,連接器就要開(kāi)始通過(guò)用戶(hù)名和密碼來(lái)驗(yàn)證你的身份盗扒。若用戶(hù)名和密碼不對(duì),就會(huì)收到一個(gè)“Access denied for user”的錯(cuò)誤形导,然后客戶(hù)端程序結(jié)束執(zhí)行环疼。若認(rèn)證通過(guò),連接器會(huì)到權(quán)限表里查出你所擁有的權(quán)限朵耕。之后這個(gè)連接里的權(quán)限判斷邏輯炫隶,都將依賴(lài)于此時(shí)讀到的權(quán)限。
這就意味著阎曹,一個(gè)用戶(hù)建立連接后伪阶,即使你用管理員賬號(hào)對(duì)這個(gè)用戶(hù)的權(quán)限做了修改,也不會(huì)影響已經(jīng)存在連接的權(quán)限处嫌。
連接完成之后栅贴,如果你沒(méi)有后續(xù)的動(dòng)作,這個(gè)連接就處于空閑狀態(tài)熏迹,你可以在show processlist 命令中看到它檐薯。下圖是該命令顯示的結(jié)果,其中Command 列顯示為Sleep 這一行在系統(tǒng)中有一個(gè)空閑連接。


客戶(hù)端如果長(zhǎng)時(shí)間沒(méi)進(jìn)行操作坛缕,連接器就會(huì)自動(dòng)將其斷開(kāi)墓猎。這個(gè)時(shí)間參數(shù)為wait_timeout進(jìn)行控制的,默認(rèn)為8小時(shí)赚楚。
如果在連接被斷開(kāi)之后毙沾,客戶(hù)端再次發(fā)送請(qǐng)求的話(huà),就會(huì)收到一個(gè)錯(cuò)誤提醒:lost connection to MySQL server during query,這時(shí)如果你要繼續(xù)宠页,就需要重連左胞,然后再執(zhí)行請(qǐng)求。
數(shù)據(jù)庫(kù)里面举户,長(zhǎng)連接是指連接成功后烤宙,如果客戶(hù)端持續(xù)有請(qǐng)求,則一直使用同一個(gè)連接敛摘。短連接則是指每次執(zhí)行完很少得幾次查詢(xún)就斷開(kāi)連接门烂,下次查詢(xún)?cè)谥匦陆⒁粋€(gè)乳愉。建立連接的過(guò)程通常是比較復(fù)雜的兄淫,盡量減少建立連接的動(dòng)作,也就是盡量使用長(zhǎng)連接蔓姚。
但是全部使用長(zhǎng)連接后捕虽,你可能會(huì)發(fā)現(xiàn),有時(shí)候MySQL占用內(nèi)存漲的特別快坡脐,這是因?yàn)镸ySQL 在執(zhí)行過(guò)程中臨時(shí)使用內(nèi)存是管理在連接對(duì)象里面的泄私。這些資源會(huì)在連接斷開(kāi)的時(shí)候才釋放。所以如果連接積累下來(lái)备闲,可能導(dǎo)致內(nèi)存占用太大晌端,被系統(tǒng)強(qiáng)行殺掉(OOM),從現(xiàn)象看就是MySQL異常重啟了。
怎么解決MySQL占用內(nèi)存過(guò)多資源恬砂?

  • 1咧纠、定期斷開(kāi)長(zhǎng)連接。使用一段時(shí)間泻骤,或者程序里判斷執(zhí)行一個(gè)占內(nèi)存的大查詢(xún)后漆羔,斷開(kāi)連接,之后要查詢(xún)?cè)僦剡B接狱掂。
  • 2演痒、如果你用MySQL 5.7或者更新的版本,可以在每次執(zhí)行一個(gè)比較大的操作后趋惨,通過(guò)執(zhí)行mysql_connection來(lái)重新初始化連接資源鸟顺。這個(gè)過(guò)程不需要重連和重新做權(quán)限驗(yàn)證,但是會(huì)將連接恢復(fù)到剛剛創(chuàng)建完時(shí)的狀態(tài)器虾。
    4讯嫂、查詢(xún)緩存
    連接建立完成后养筒,就可以進(jìn)行查詢(xún)select語(yǔ)句。執(zhí)行邏輯就會(huì)來(lái)到第二步:查詢(xún)緩存端姚。
    MySQL 拿到一個(gè)查詢(xún)請(qǐng)求后晕粪,會(huì)先到查詢(xún)緩存看看,之前是不是執(zhí)行這條語(yǔ)句渐裸。之前執(zhí)行過(guò)的語(yǔ)句及結(jié)果可能會(huì)以key-value對(duì)形式巫湘,被直接緩存在內(nèi)存中。key是查詢(xún)的語(yǔ)句昏鹃,value是查詢(xún)的結(jié)果尚氛。如果你的查詢(xún)能夠直接在這個(gè)緩存中找到key,那么這個(gè)value就會(huì)被直接返回給客戶(hù)端洞渤。
    如果語(yǔ)句不在查詢(xún)緩存中阅嘶,就會(huì)繼續(xù)后面的執(zhí)行階段。執(zhí)行完成后载迄,執(zhí)行結(jié)果會(huì)被存入查詢(xún)緩存中讯柔。你可以看到,如果查詢(xún)命中緩存护昧,MySQL不需要執(zhí)行后面的復(fù)雜操作魂迄,就可以直接返回結(jié)果,這個(gè)效率會(huì)很高惋耙。
    但是大多數(shù)情況下我會(huì)建議你不要使用查詢(xún)緩存捣炬,為什么呢?因?yàn)椴樵?xún)緩存往往弊大于利绽榛。
    查詢(xún)緩存的失效非常頻繁湿酸,只要對(duì)一個(gè)表的更新,這個(gè)表上所有的查詢(xún)緩存都會(huì)被清空灭美。
    好在MySQL也提供了這種''按需使用''的方式推溃。你可以將參數(shù)query_cache_type設(shè)置成demand ,這樣對(duì)于默認(rèn)的SQL語(yǔ)句都不使用查詢(xún)緩存。而對(duì)于你確認(rèn)要使用查詢(xún)緩存的語(yǔ)句冲粤,可以用SQL_cache顯示指定美莫,像下面的語(yǔ)句一樣:

mysql> select SQL_CACHE * from T where ID=10;

需要注意的是梯捕,MySQL8.0版本直接將查詢(xún)緩存的整塊功能刪掉厢呵,也就是8.0開(kāi)始徹底沒(méi)有這個(gè)功能。
5傀顾、分析器
如果沒(méi)有命中查詢(xún)緩存襟铭,就要開(kāi)始真正執(zhí)行語(yǔ)句,首先在查詢(xún)前,MySQL需要知道你要做什么寒砖,因此需要對(duì)SQL語(yǔ)句進(jìn)行語(yǔ)句解析赐劣。
分析器先會(huì)做詞法分析,你所輸入的SQL語(yǔ)句是由多個(gè)字符串和空格組成哩都,MySQL需要識(shí)別這些字符串分別是什么魁兼,代表什么意思。
MySQL從你輸入的select這個(gè)關(guān)鍵字識(shí)別出來(lái)漠嵌,這是一個(gè)查詢(xún)語(yǔ)句咐汞。它要把字符串"T"識(shí)別成表名''T'' ,把字符串"ID"識(shí)別成''列ID'' 儒鹿。

mysql> elect * from t where ID=1;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'elect * from t where ID=1' at line 1

一般語(yǔ)法錯(cuò)誤會(huì)提示第一個(gè)出現(xiàn)錯(cuò)誤的位置化撕,所以你要關(guān)注的就是緊接"use near"的內(nèi)容。
6约炎、優(yōu)化器
經(jīng)過(guò)了分析器植阴,MySQL就知道你要做什么了。在開(kāi)始執(zhí)行之前圾浅,還要經(jīng)過(guò)優(yōu)化器處理掠手。
優(yōu)化器是在表里有很多個(gè)索引的時(shí)候,決定使用哪個(gè)索引贱傀;或者在一個(gè)語(yǔ)句有多表關(guān)聯(lián)(join)的時(shí)候惨撇,決定各個(gè)表的連接順序。比如你執(zhí)行下面這樣的語(yǔ)句府寒,這個(gè)語(yǔ)句是執(zhí)行兩個(gè)表的join:

mysql> select * from t1 join t2 using(ID) where t1.c=10 and t2.d=20;

  • 既可以先從表t1里面取出c=10的記錄的ID值,在根據(jù)ID值關(guān)聯(lián)到表t2报腔,再判斷t2里面的d的值是否等于20株搔。
  • 也可以先從表t2里面取出d=20的記錄的ID值,再根據(jù)ID值關(guān)聯(lián)到t1,在判斷t1里面的c的值是否等于10纯蛾。

t1-t2表

這兩種執(zhí)行方法的邏輯結(jié)果是一樣的纤房,但是執(zhí)行的效率會(huì)有不同,而優(yōu)化器的作用就是決定選擇使用哪一個(gè)方案翻诉。
優(yōu)化器階段完成后炮姨,這個(gè)語(yǔ)句的執(zhí)行方案就確定下來(lái)了,然后進(jìn)入執(zhí)行器階段碰煌。如果你還有一些疑問(wèn)舒岸,比如優(yōu)化器是怎么選擇的,有沒(méi)有可能選擇錯(cuò)等等芦圾。
7蛾派、執(zhí)行器
MySQL通過(guò)分析器知道了你要做什么,通過(guò)優(yōu)化器知道了該怎么做,于是就進(jìn)入了執(zhí)行器階段洪乍。
開(kāi)始執(zhí)行的時(shí)候眯杏,要先判斷一下你對(duì)這個(gè)表T是否有執(zhí)行查詢(xún)的權(quán)限,如果沒(méi)有壳澳,就會(huì)返回沒(méi)去權(quán)限的錯(cuò)誤岂贩,如下所示。

mysql> select * from T where ID=10;
ERROR 1142 (42000): SELECT command denied to user 'b'@'localhost' for table 'T'

如果有權(quán)限巷波,就打開(kāi)表繼續(xù)執(zhí)行河闰。當(dāng)打開(kāi)表的時(shí)候,執(zhí)行器就會(huì)根據(jù)表的引擎定義褥紫,去使用這個(gè)引擎提供的接口姜性。
比如我們這個(gè)例子中的表T中,ID字段沒(méi)有索引髓考,那么執(zhí)行流程是這樣的:

  • 1部念、調(diào)用InnoDB引擎接口取這個(gè)表的第一行,判斷ID值是不是10氨菇,如果不是則跳過(guò)儡炼,如果是則將這行結(jié)果集中;
  • 2查蓉、調(diào)用引擎接口取"下一行"乌询,重復(fù)相同的判斷邏輯,直到取到這個(gè)表的最后一行豌研。
  • 3妹田、執(zhí)行器將上述遍歷過(guò)程中所有滿(mǎn)足條件的行組成的記錄集作為結(jié)果返回給客戶(hù)端。
    至此鹃共,這個(gè)執(zhí)行語(yǔ)句就執(zhí)行結(jié)束鬼佣。
    對(duì)于有索引的表,執(zhí)行的邏輯也差不多霜浴。第一次調(diào)用的是"取滿(mǎn)足條件的第一行"這個(gè)接口晶衷,之后循環(huán)取"滿(mǎn)足條件的下一行"這個(gè)接口,這些接口都是引擎中已經(jīng)定義好的阴孟。
    你會(huì)在數(shù)據(jù)庫(kù)的慢查詢(xún)?nèi)罩局锌吹揭粋€(gè) rows_examined的字段晌纫,表示這個(gè)語(yǔ)句執(zhí)行過(guò)程中掃描了多少行。這個(gè)值就是在執(zhí)行器每次調(diào)用引擎獲取數(shù)據(jù)行的時(shí)候累加的永丝。
    在有些場(chǎng)景下锹漱,執(zhí)行器調(diào)用一次,在引擎獲內(nèi)部則掃描了多少行类溢,因此引擎描行數(shù)跟rows_examined 并不是完全相同的凌蔬。
    問(wèn)題
    如果表T中沒(méi)有字段K露懒,而你執(zhí)行了這個(gè)語(yǔ)句 select * from T where k=1 , 那肯定會(huì)報(bào)"不存在"錯(cuò)誤:"Unknown column 'k' in 'where clause' "。

    是分析器
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末砂心,一起剝皮案震驚了整個(gè)濱河市懈词,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌辩诞,老刑警劉巖坎弯,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異译暂,居然都是意外死亡抠忘,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)外永,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)崎脉,“玉大人,你說(shuō)我怎么就攤上這事伯顶∏糇疲” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵祭衩,是天一觀(guān)的道長(zhǎng)灶体。 經(jīng)常有香客問(wèn)我,道長(zhǎng)掐暮,這世上最難降的妖魔是什么蝎抽? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮路克,結(jié)果婚禮上樟结,老公的妹妹穿的比我還像新娘。我一直安慰自己衷戈,他們只是感情好狭吼,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著殖妇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪破花。 梳的紋絲不亂的頭發(fā)上谦趣,一...
    開(kāi)封第一講書(shū)人閱讀 52,255評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音座每,去河邊找鬼前鹅。 笑死,一個(gè)胖子當(dāng)著我的面吹牛峭梳,可吹牛的內(nèi)容都是我干的舰绘。 我是一名探鬼主播蹂喻,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼捂寿!你這毒婦竟也來(lái)了口四?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤秦陋,失蹤者是張志新(化名)和其女友劉穎蔓彩,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體驳概,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡赤嚼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了顺又。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片更卒。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖稚照,靈堂內(nèi)的尸體忽然破棺而出蹂空,到底是詐尸還是另有隱情,我是刑警寧澤锐锣,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布腌闯,位于F島的核電站,受9級(jí)特大地震影響雕憔,放射性物質(zhì)發(fā)生泄漏姿骏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一斤彼、第九天 我趴在偏房一處隱蔽的房頂上張望分瘦。 院中可真熱鬧,春花似錦琉苇、人聲如沸嘲玫。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)去团。三九已至,卻和暖如春穷蛹,著一層夾襖步出監(jiān)牢的瞬間土陪,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工肴熏, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鬼雀,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓蛙吏,卻偏偏與公主長(zhǎng)得像源哩,于是被迫代替她去往敵國(guó)和親鞋吉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359

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