對(duì)于MySQL而言,其實(shí)分為客戶(hù)端與服務(wù)端佃迄。
服務(wù)端泼差,就是MySQL應(yīng)用,當(dāng)我們使用net start mysql命令啟動(dòng)的服務(wù)呵俏,其實(shí)就是啟動(dòng)了MySQL的服務(wù)端堆缘。
客戶(hù)端,負(fù)責(zé)發(fā)送請(qǐng)求到服務(wù)端并從服務(wù)端獲取數(shù)據(jù)柴信,客戶(hù)端可以有多種形式套啤,可以是我們通過(guò)mysql -uroot -p1234打開(kāi)的黑窗口,也可以是我們使用的Nativecat随常、SQLyog等數(shù)據(jù)庫(kù)連接工具潜沦,甚至我們的程序,也可以稱(chēng)作MySQL的客戶(hù)端绪氛。
而當(dāng)我們?cè)趍ysql窗口或者數(shù)據(jù)庫(kù)連接工具中輸入一句sql后唆鸡,我們就可以獲取到想要的數(shù)據(jù),這中間MySQL到底是怎么工作的呢枣察?
在我們執(zhí)行SQL后争占,例如一句簡(jiǎn)單的select * from user where name = ‘yanger’,客戶(hù)端發(fā)送請(qǐng)求到服務(wù)端序目,請(qǐng)求到達(dá)Server層臂痕,會(huì)經(jīng)過(guò)連接器、查詢(xún)緩存猿涨、分析器握童、優(yōu)化器、執(zhí)行器等叛赚,最終通過(guò)存儲(chǔ)引擎從文件系統(tǒng)獲取數(shù)據(jù)或者插入數(shù)據(jù)到文件系統(tǒng)澡绩。
連接器
在客戶(hù)端程序發(fā)起連接的時(shí)候,需要攜帶主機(jī)信息俺附、用戶(hù)名肥卡、密碼,服務(wù)器程序會(huì)對(duì)客戶(hù)端程序提供的這些信息進(jìn)行認(rèn)證事镣,如果認(rèn)證失敗步鉴,服務(wù)器程序會(huì)拒絕連接。
連接命令大家都比較熟悉。
mysql -h$ip -P$port -u$user -p
輸完命令之后唠叛,需要繼續(xù)輸入密碼只嚣,密碼也可以直接跟在 -p 后面,但這樣可能會(huì)導(dǎo)致你的密碼泄露艺沼,如果你連的是生產(chǎn)服務(wù)器,強(qiáng)烈建議你不要這么做蕴掏。
MySQL采用TCP作為服務(wù)器和客戶(hù)端之間的網(wǎng)絡(luò)通信協(xié)議障般,完成 TCP 握手后,連接器主要做密碼校驗(yàn)和權(quán)限獲取盛杰。
如果用戶(hù)名或密碼不對(duì)挽荡,你就會(huì)收到一個(gè)"Access denied for user"的錯(cuò)誤
如果用戶(hù)名密碼認(rèn)證通過(guò),連接器會(huì)到權(quán)限表里面查出你擁有的權(quán)限即供。之后定拟,這個(gè)連接里面的權(quán)限判斷邏輯,都將依賴(lài)于此時(shí)讀到的權(quán)限
MySQL的默認(rèn)連接是8小時(shí)逗嫡,由參數(shù) wait_timeout 控制的青自,如果超過(guò)這個(gè)時(shí)間不使用,會(huì)自動(dòng)斷開(kāi)驱证,并在之后的操作中延窜,拋出Lost connection to MySQL server during query的錯(cuò)誤。
查詢(xún)緩存
針對(duì)于查詢(xún)語(yǔ)句抹锄,MySQL 拿到一個(gè)查詢(xún)請(qǐng)求后逆瑞,會(huì)先到查詢(xún)緩存看看,之前是不是執(zhí)行過(guò)這條語(yǔ)句伙单,之前執(zhí)行過(guò)的語(yǔ)句及其結(jié)果可能會(huì)以 key-value 對(duì)的形式获高,被直接緩存在內(nèi)存中。如果命中緩存吻育,將直接返回結(jié)果念秧。如果不在查詢(xún)緩存中,就會(huì)繼續(xù)后面的執(zhí)行階段扫沼。執(zhí)行完成后出爹,執(zhí)行結(jié)果會(huì)被存入查詢(xún)緩存中。
針對(duì)于更新語(yǔ)句缎除,包含插入刪除語(yǔ)句严就,MySQL 收到更新請(qǐng)求時(shí),會(huì)把查詢(xún)緩存中該表相關(guān)的緩存數(shù)據(jù)全部清空器罐。
我們可以看到梢为,只要有更新,緩存就會(huì)失效,而對(duì)于正常的業(yè)務(wù)铸董,更新其實(shí)是比較頻繁的祟印,也就是說(shuō),其實(shí)MySQL的查詢(xún)緩存命中率并不會(huì)很高粟害,所以建議一般不到開(kāi)啟蕴忆。
可以通過(guò)設(shè)置 query_cache_type 為 DEMAND 來(lái)關(guān)閉查詢(xún)緩存功能。而事實(shí)上悲幅,在 MySQL 8.0 版本套鹅,更是直接移除了查詢(xún)緩存這一個(gè)功能。
分析器
MySQL 首先需要對(duì)SQL語(yǔ)句進(jìn)行分析汰具,分析過(guò)程本質(zhì)上算是一個(gè)編譯過(guò)程卓鹿,涉及詞法解析、語(yǔ)法分析留荔、語(yǔ)義分析等階段吟孙,通過(guò)分析MySQL知道自己要做什么。
如果語(yǔ)句不對(duì)聚蝶,就會(huì)收到“You have an error in your SQL syntax”的錯(cuò)誤提醒杰妓,一般語(yǔ)法錯(cuò)誤會(huì)提示第一個(gè)出現(xiàn)錯(cuò)誤的位置,所以你要關(guān)注的是緊接“use near”的內(nèi)容既荚。
優(yōu)化器
面對(duì)分析器拿到的結(jié)果稚失,MySQL會(huì)做一些優(yōu)化處理,例如在表里面有多個(gè)索引的時(shí)候恰聘,決定使用哪個(gè)索引句各,或者在一個(gè)語(yǔ)句有多表關(guān)聯(lián)(join)的時(shí)候,決定各個(gè)表的連接順序晴叨。
優(yōu)化的結(jié)果就是生成一個(gè)執(zhí)行計(jì)劃凿宾,這個(gè)執(zhí)行計(jì)劃表明了應(yīng)該使用哪些索引進(jìn)行查詢(xún),表之間的連接順序是啥樣的兼蕊。我們可以使用EXPLAIN語(yǔ)句來(lái)查看某個(gè)語(yǔ)句的執(zhí)行計(jì)劃初厚。
這里\G在命令窗口無(wú)法一行時(shí),可以豎著展示結(jié)果孙技,方便查看产禾。
執(zhí)行器
經(jīng)過(guò)了分析器和優(yōu)化器,就正式進(jìn)行執(zhí)行階段了牵啦,不過(guò)執(zhí)行之前亚情,需要做權(quán)限驗(yàn)證,如果權(quán)限不足哈雏,就會(huì)拋出權(quán)限的錯(cuò)誤楞件。其實(shí)在查詢(xún)緩存的時(shí)候衫生,一樣也會(huì)進(jìn)行權(quán)限校驗(yàn)。
如果通過(guò)驗(yàn)證土浸,執(zhí)行器就打開(kāi)表繼續(xù)執(zhí)行罪针。打開(kāi)表的時(shí)候,執(zhí)行器就會(huì)根據(jù)表的引擎定義黄伊,去使用這個(gè)引擎提供的接口泪酱。
存儲(chǔ)引擎
MySQL支持非常多種存儲(chǔ)引擎,常用的是InnoDB和MyISAM还最,MySQL的默認(rèn)存儲(chǔ)引擎是InnoDB西篓。
假如我們選擇是InnoDB引擎,對(duì)于查詢(xún)憋活,那InnoDB 會(huì)取這個(gè)表的第一行來(lái)進(jìn)行判斷是不是符合要求,符合則存在結(jié)果集中虱黄,否則繼續(xù)進(jìn)行下一行悦即,直到該表的最后一行。
然后存儲(chǔ)引擎將結(jié)果返回給執(zhí)行器橱乱, 執(zhí)行器拿著結(jié)果返回給客戶(hù)端辜梳,這樣一句SQL就執(zhí)行完成了。