一嚎研、背景
為什么我先學(xué)習(xí)MySQL的基礎(chǔ)架構(gòu)呢? 原因很簡單, 當(dāng)我們需要了解一項(xiàng)新事物的時候, 我們只有站在宏觀的層面, 才能層層的去理解問題, 舉個例子, 我們要看一個框架的源碼, 一開始鉆研進(jìn)去研究, 發(fā)現(xiàn)就有點(diǎn) "丈二的和尚摸不著頭腦"罢低。因?yàn)槲覀儧]有自己的了解他,不知道他的入口在哪钥屈?
看一個事兒千萬不要直接陷入細(xì)節(jié)里辅肾,你應(yīng)該先鳥瞰其全貌,這樣能夠幫助你從高維度理解問題
<MySQL 45 講>
二、MySQL 基本架構(gòu)
(MySQL 邏輯架構(gòu)圖)
從圖中我們可以清晰的看到, SQL 語句在MySQL的各個功能模塊中的執(zhí)行過程, 總結(jié)一下可以分為 Server 層 和 存儲引擎 兩個部分术健。
-
Server層
Server層包括連接器、查詢緩存粘衬、分析器荞估、優(yōu)化器、執(zhí)行器等稚新,涵蓋了 MySQL 的大多數(shù)核心服務(wù)功能, 以及所有的內(nèi)置函數(shù) (如 時間, 日期, 數(shù)學(xué)函數(shù) 等), 所有跨存儲引擎的功能都在這實(shí)現(xiàn), 存儲過程, 視圖, 觸發(fā)器等.
-
存儲引擎
存儲引擎負(fù)責(zé)數(shù)據(jù)的存儲和提取勘伺。架構(gòu)模式是插件式的,支持InnoDB, MyISAM, Memory等 多個存儲引擎. MySQL 5.5.5 版本開始, InnoDB 成為默認(rèn)存儲引擎褂删。
連接器
功能作用:負(fù)責(zé)跟客戶端建立連接飞醉、獲取權(quán)限、維持和管理連接屯阀,如用戶名密碼認(rèn)證通過缅帘,連接器會到權(quán)限表里面查出你擁有的權(quán)限。之后蹲盘,這個連接里面的權(quán)限判斷邏輯股毫,都將依賴于此時讀到的權(quán)限。修改完成后召衔,只有再新建的連接才會使用新的權(quán)限設(shè)置
連接對象:MySQL 在執(zhí)行過程中臨時使用的內(nèi)存是管理在連接對象里面的铃诬,這些資源會在連接斷開的時候才釋放。
注意點(diǎn):
在用戶成功連接后,即使你用管理員賬號對該用戶進(jìn)行了權(quán)限更改,也不會影響已經(jīng)存在連接的權(quán)限苍凛。如果想要權(quán)限生效趣席,只有在新建的連接才會使用新的權(quán)限設(shè)置。
長連接引發(fā)的思考:
風(fēng)險問題:MySQL在執(zhí)行過程中臨時使用的內(nèi)存是管理在連接里面的, 這些資源只有斷開的時候才會釋放, 長連接累積下來框产,可能會導(dǎo)致內(nèi)存占用過大,被系統(tǒng)強(qiáng)行殺掉(OOM)
解決方案:定期斷開長鏈接,使用一段時間错洁,或者執(zhí)行一個占用內(nèi)存大的查詢后秉宿,斷開連接,在進(jìn)行重連屯碴。如果使用的是MySQL5.7或者更新的版本, 在每次執(zhí)行比較大的操作后,通過 mysql_reset_connection重新初始化連接資源, 這個過程中不需要重連和進(jìn)行權(quán)限驗(yàn)證的,但是會恢復(fù)到剛剛創(chuàng)建的狀態(tài)描睦。
數(shù)據(jù)庫里面宣肚,長連接是指連接成功后,如果客戶端持續(xù)有請求悠栓,則一直使用同一個連接霉涨。短連接則是指每次執(zhí)行完很少的幾次查詢就斷開連接按价,下次查詢再重新建立一個。
長鏈接在數(shù)據(jù)庫中笙瑟,每次建立連接是比較復(fù)雜的楼镐,所以在使用中盡量減少建立連接的動作,就是使用長鏈接往枷。查詢緩存
存儲方式:是以 key-value的形式進(jìn)行緩存在內(nèi)存中的,key 是查詢的語句导而,value 是查詢的結(jié)果酌摇。如果你的查詢能夠直接在這個緩存中找到 key,那么這個 value 就會被直接返回給客戶端嗡载。
風(fēng)險:大多數(shù)情況下我會建議你不要使用查詢緩存,為什么呢仍稀?因?yàn)椴樵兙彺嫱状笥诶莨觥2樵兙彺娴氖Х浅nl繁,只要有對一個表的更新技潘,這個表上所有的查詢緩存都會被清空遥巴。MySQL 8.0 版本直接將查詢緩存的整塊功能刪掉了,也就是說 8.0 開始徹底沒有這個功能了享幽。
分析器
詞法分析:識別出 SQL 語句里面的字符串分別是什么铲掐,代表什么,把 SQL 語句中字符串 T 識別成“表名 T值桩,把字符串 ID 識別成 列ID
語法分析:根據(jù)詞法分析的結(jié)果摆霉,語法分析器會根據(jù)語法規(guī)則,判斷你輸入的這個 SQL 語句是否滿足 MySQL 語法
優(yōu)化器
功能作用:優(yōu)化器是在表里面有多個索引的時候奔坟,決定使用哪個索引携栋;或者在一個語句有多表關(guān)聯(lián)(join)的時候,決定各個表的連接順序
優(yōu)化器
查詢語句:
調(diào)用 InnoDB 引擎接口取這個表的第一行咳秉,判斷 ID 值是不是 5婉支,如果不是則跳過,如果是則將這行存在結(jié)果集中
調(diào)用引擎接口取 下一行澜建,重復(fù)相同的判斷邏輯向挖,直到取到這個表的最后一行
執(zhí)行器將上述遍歷過程中所有滿足條件的行組成的記錄集作為結(jié)果集返回給客戶端
更新語句
執(zhí)行器先找引擎取 ID=2 這一行蝌以,ID 是主鍵,引擎直接用樹搜索找到這一行何之,如果 ID=2 這一行所在的數(shù)據(jù)頁本來就在內(nèi)存中跟畅,就直接返回給執(zhí)行器,否則帝美,需要先從磁盤讀入內(nèi)存碍彭,然后再返回。
執(zhí)行器拿到引擎給的行數(shù)據(jù)悼潭,把這個值加上 1庇忌,比如原來是 N,現(xiàn)在就是 N+1舰褪,得到新的一行數(shù)據(jù)皆疹,再調(diào)用引擎接口寫入這行新數(shù)據(jù)
引擎將這行新數(shù)據(jù)更新到內(nèi)存中,同時將這個更新操作記錄到 redo log 里面占拍,此時 redo log 處于 prepare 狀態(tài)略就。然后告知執(zhí)行器執(zhí)行完成了,隨時可以提交事務(wù)
執(zhí)行器生成這個操作的 binlog晃酒,并把 binlog 寫入磁盤
執(zhí)行器調(diào)用引擎的提交事務(wù)接口表牢,引擎把剛剛寫入的 redo log 改成提交(commit)狀態(tài),更新完成