一篇學(xué)會(huì) MySQL 體系架構(gòu)
前面三篇文章我們一起分析了外部環(huán)境對(duì) MySQL 性能的影響,不過(guò)起決定作用的還是 MySQL 自身,今天我們就來(lái)看看 MySQL 體系架構(gòu),看看這個(gè)數(shù)據(jù)庫(kù)到底是怎么組成的。
MySQL 是一個(gè)典型的 C/S 架構(gòu)應(yīng)用程序,MySQL Server 提供數(shù)據(jù)庫(kù)服務(wù),完成客戶端的請(qǐng)求和操作,Client 則負(fù)責(zé)連接到 Server。很多初學(xué)者并不太容易區(qū)分出 MySQL Server 和 Client,因?yàn)楫?dāng)我們安裝完 MySQL 之后,默認(rèn)情況下 Server 和 Client 就都具備了,我們?cè)诿钚羞B接并登錄 MySQL 服務(wù),這個(gè)其實(shí)就是由 Client 提供的服務(wù)。MySQL 和其他關(guān)系型數(shù)據(jù)庫(kù)不一樣的地方在于它的彈性以及可以通過(guò)插件形式提供不同種類(lèi)的存儲(chǔ)引擎,MySQL 請(qǐng)求處理過(guò)程會(huì)根據(jù)不同的存儲(chǔ)引擎發(fā)生變化,這是它的特色。
1、MySQL 存儲(chǔ)引擎
這里我主要和大家介紹下 MySQL 存儲(chǔ)引擎的歷史,至于每一個(gè)存儲(chǔ)引擎的特點(diǎn),松哥將在后面的文章中和大家詳細(xì)介紹。
MySQL 從設(shè)計(jì)之初,存儲(chǔ)引擎就是可插拔的,允許公司或者個(gè)人按照自己的需求定義自己的存儲(chǔ)引擎(當(dāng)然,普通的公司或者個(gè)人其實(shí)是沒(méi)有這個(gè)實(shí)力的)。MySQL 自研的使用較廣的存儲(chǔ)引擎是 MyISAM ,MyISAM 支持表鎖,不支持行鎖,所以在處理高并發(fā)寫(xiě)操作時(shí)效率要低一些,另外 MyISAM 也不支持外鍵(雖然現(xiàn)在實(shí)際項(xiàng)目中外鍵已經(jīng)用的比較少了)。
雖然 MyISAM 看起來(lái)有些簡(jiǎn)陋,但這并不影響 MySQL 的流行,這就不得不說(shuō) MySQL 中另外一個(gè)大名鼎鼎的存儲(chǔ)引擎 InnoDB 了。
InnoDB 存儲(chǔ)引擎是由一家位于芬蘭赫爾辛基的名為 Innobase Oy 的公司開(kāi)發(fā)的,InnoDB 存儲(chǔ)引擎的歷史甚至比 MySQL 還要悠久??赡軙?huì)有小伙伴決定奇怪,插件竟然比起宿主還要?dú)v史悠久?
InnoDB 剛剛開(kāi)發(fā)的時(shí)侯,就是作為一個(gè)完整的數(shù)據(jù)庫(kù)來(lái)開(kāi)發(fā)的,因此功能很完備。開(kāi)發(fā)出來(lái)之后,創(chuàng)始人是想將這個(gè)數(shù)據(jù)庫(kù)賣(mài)掉的,但是沒(méi)有找到買(mǎi)家。
后來(lái) MySQL2.0 推出后,這種可插拔的存儲(chǔ)引擎吸引了 Innobase Oy 公司創(chuàng)始人 Heikki Tuuri 的注意,在和 MySQL 溝通之后,決定將 InnoDB 作為一個(gè)存儲(chǔ)引擎引入到 MySQL 中(這就是為什么 InnoDB 比 MySQL 還歷史悠久的原因),MySQL 雖然支持 InnoDB ,但是實(shí)際上還是主推自家的 MyISAM。
但是 InnoDB 實(shí)在太優(yōu)秀了,最終在 2006 年的時(shí)侯,成功吸引到大魔王 Oracle 的注意,大手一揮,就把 InnoDB 收購(gòu)了。
MySQL 主推自家的 MyISAM ,日子過(guò)得也很慘淡,最終在 2008 年被 sun 公司以 10 億美元拿下,這個(gè)操作鞏固了 sun 在開(kāi)源領(lǐng)域的領(lǐng)袖地位,可是一直以來(lái) sun 公司的變現(xiàn)能力都比較弱,最終 sun 自己在 2009 年被 Oracle 收入囊中。
Oracle 收購(gòu) sun 之后,InnoDB 和 MySQL 就都成了 Oracle 的產(chǎn)品了,這下整合就變得非常容易了,在后來(lái)發(fā)布的版本中,InnoDB 慢慢就成為了 MySQL 的默認(rèn)存儲(chǔ)引擎。在最新的 MySQL8 中,元數(shù)據(jù)表也使用了 InnoDB 作為存儲(chǔ)引擎。
InnoDB 存儲(chǔ)引擎主要有如下特點(diǎn):
- 支持事務(wù)
- 支持 4 個(gè)級(jí)別的事務(wù)隔離
- 支持多版本讀
- 支持行級(jí)鎖
- 讀寫(xiě)阻塞與事務(wù)隔離級(jí)別相關(guān)
- 支持緩存,既能緩存索引,也能緩存數(shù)據(jù)
- 整個(gè)表和主鍵以 Cluster 方式存儲(chǔ),組成一顆平衡樹(shù)
當(dāng)然也不是說(shuō) InnoDB 一定就是好的,在實(shí)際開(kāi)發(fā)中,還是要根據(jù)具體的場(chǎng)景來(lái)選擇到底是使用 InnoDB 還是 MyISAM 。
MyIASM(該引擎在 5.5 前的 MySQL 數(shù)據(jù)庫(kù)中為默認(rèn)存儲(chǔ)引擎)特點(diǎn):
- MyISAM 沒(méi)有提供對(duì)數(shù)據(jù)庫(kù)事務(wù)的支持
- 不支持行級(jí)鎖和外鍵
- 由于 2,導(dǎo)致當(dāng)執(zhí)行 INSERT 插入或 UPDATE 更新語(yǔ)句時(shí),即執(zhí)行寫(xiě)操作需要鎖定整個(gè)表,所以會(huì)導(dǎo)致效率降低
- MyISAM 保存了表的行數(shù),當(dāng)執(zhí)行 SELECT COUNT(*) FROM TABLE 時(shí),可以直接讀取相關(guān)值,不用全表掃描,速度快。
兩者區(qū)別:
- MyISAM 是非事務(wù)安全的,而 InnoDB 是事務(wù)安全的
- MyISAM 鎖的粒度是表級(jí)的,而 InnoDB 支持行級(jí)鎖
- MyISAM 支持全文類(lèi)型索引,而 InnoDB 在 MySQL5.6 之前不支持全文索引,從 MySQL5.6 之后開(kāi)始支持 FULLTEXT 索引了(https://dev.mysql.com/doc/refman/5.6/en/mysql-nutshell.html)。
使用場(chǎng)景比較:
- 如果要執(zhí)行大量 select 操作,應(yīng)該選擇 MyISAM
- 如果要執(zhí)行大量 insert 和 update 操作,應(yīng)該選擇 InnoDB
- 大尺寸的數(shù)據(jù)集趨向于選擇 InnoDB 引擎,因?yàn)樗С质聞?wù)處理和故障恢復(fù)。數(shù)據(jù)庫(kù)的大小決定了故障恢復(fù)的時(shí)間長(zhǎng)短,InnoDB 可以利用事務(wù)日志進(jìn)行數(shù)據(jù)恢復(fù),這會(huì)比較快。主鍵查詢?cè)?InnoDB 引擎下也會(huì)相當(dāng)快,不過(guò)需要注意的是如果主鍵太長(zhǎng)也會(huì)導(dǎo)致性能問(wèn)題。
相對(duì)來(lái)說(shuō),InnoDB 在互聯(lián)網(wǎng)公司使用更多一些。
這是我們對(duì) MySQL 存儲(chǔ)引擎的一個(gè)簡(jiǎn)略介紹,后面松哥會(huì)專(zhuān)門(mén)寫(xiě)文章來(lái)詳細(xì)介紹每一種存儲(chǔ)引擎的特點(diǎn),歡迎大家一起來(lái)討論。
2、MySQL 架構(gòu)
接下來(lái)我們?cè)賮?lái)看看 MySQL 的軟件架構(gòu)(圖片源自網(wǎng)絡(luò))。
從上圖我們可以大概看出來(lái),MySQL 架構(gòu)大致上可以分為三層:
- 客戶端(應(yīng)用層)
- 服務(wù)層
- 存儲(chǔ)引擎層
我們分別來(lái)看。
2.1 客戶端
基本上所有的 C/S 架構(gòu)的程序都有一個(gè)客戶端層,這一層主要包含如下三方面的內(nèi)容:
- 連接處理:當(dāng)一個(gè)客戶端向服務(wù)端發(fā)送連接請(qǐng)求后,MySQL Server 會(huì)從線程池中分配一個(gè)線程來(lái)和客戶端進(jìn)行連接,以后該客戶端的請(qǐng)求都會(huì)被分配到該線程上。MySQL Server 為了提高性能,提供了線程池,減少了創(chuàng)建線程和釋放線程所花費(fèi)的時(shí)間。主流的程序設(shè)計(jì)語(yǔ)言都可以使用各自的 API 來(lái)與 MySQL 建立連接。
- 用戶認(rèn)證:當(dāng)客戶端向 MySQL 服務(wù)端發(fā)起連接請(qǐng)求后,MySQL Server 會(huì)對(duì)發(fā)起連接的用戶進(jìn)行認(rèn)證處理,MySQL 認(rèn)證依據(jù)是: 用戶名,客戶端主機(jī)地址和用戶密碼。
- 用戶鑒權(quán):當(dāng)客戶連接到 MySQL Server 后,MySQL Server 會(huì)根據(jù)用戶的權(quán)限來(lái)判斷用戶具體可執(zhí)行哪些操作。
2.2 服務(wù)層
MySQL 服務(wù)層的東西主要有六方面,我們來(lái)逐個(gè)分析。
2.2.1 系統(tǒng)管理和控制工具
- 數(shù)據(jù)庫(kù)備份和恢復(fù)
- 數(shù)據(jù)庫(kù)安全管理,如用戶及權(quán)限管理
- 數(shù)據(jù)庫(kù)復(fù)制管理
- 數(shù)據(jù)庫(kù)集群管理
- 數(shù)據(jù)庫(kù)分區(qū),分庫(kù),分表管理
- 數(shù)據(jù)庫(kù)元數(shù)據(jù)管理
2.2.2 連接池
這個(gè)前面已經(jīng)提到過(guò),連接池負(fù)責(zé)存儲(chǔ)和管理客戶端與數(shù)據(jù)庫(kù)的連接,一個(gè)線程管理一個(gè)連接。
2.2.3 SQL 接口
SQL 接口用來(lái)接受客戶端發(fā)送來(lái)的各種 SQL 命令,并且返回用戶需要的查詢結(jié)果。
如:
- DDL
- DML
- 存儲(chǔ)過(guò)程
- 視圖
- 觸發(fā)器
等都在這里被處理。
2.2.4 解析器
解析器的作用主要是解析查詢語(yǔ)句,將客戶端請(qǐng)求的 SQL 解析生成一個(gè)“解析樹(shù)”,然后根據(jù) MySQL 的語(yǔ)法規(guī)則檢查解析樹(shù)是否合法,如果語(yǔ)句語(yǔ)法有錯(cuò)誤,則返回相應(yīng)的錯(cuò)誤信息。
語(yǔ)法檢查通過(guò)后,解析器會(huì)查詢緩存,如果緩存中有對(duì)應(yīng)的語(yǔ)句,就直接返回結(jié)果不進(jìn)行接下來(lái)的優(yōu)化執(zhí)行操作。
2.2.5 查詢優(yōu)化器
看名字就知道,這一步主要在解析器完成解析并對(duì) SQL 語(yǔ)法進(jìn)行檢查之后,對(duì)查詢語(yǔ)句進(jìn)行優(yōu)化,主要的優(yōu)化方式包括選擇合適的索引以及數(shù)據(jù)讀取方式。
2.2.6 緩存
包括全局和引擎特定的緩存,提高查詢的效率。如果查詢緩存中有命中的查詢結(jié)果,則查詢語(yǔ)句就可以從緩存中取數(shù)據(jù),無(wú)須再通過(guò)解析和執(zhí)行。這個(gè)緩存機(jī)制是由一系列小緩存組成,如表緩存、記錄緩存、key 緩存、權(quán)限緩存等。
2.3 存儲(chǔ)引擎層
存儲(chǔ)引擎負(fù)責(zé) MySQL 中數(shù)據(jù)的存儲(chǔ)與提取,與底層系統(tǒng)文件進(jìn)行交互。
MySQL 存儲(chǔ)引擎是可插拔的,服務(wù)器中的查詢執(zhí)行引擎通過(guò)接口與存儲(chǔ)引擎進(jìn)行通信,接口屏蔽了不同存儲(chǔ)引擎之間的差異?,F(xiàn)在有很多種存儲(chǔ)引擎,各有各的特點(diǎn),最常見(jiàn)的是 MyISAM 和 InnoDB。
需要注意的是,MySQL 存儲(chǔ)引擎是針對(duì)數(shù)據(jù)表而不是針對(duì)數(shù)據(jù)庫(kù),換句話說(shuō),在同一個(gè)數(shù)據(jù)庫(kù)中,我們可以同時(shí)使用多種不同的存儲(chǔ)引擎(技術(shù)上可以,實(shí)際不推薦)。
3、小結(jié)
MySQL 的這種分層設(shè)計(jì)為我們屏蔽了很多底層的東西,例如存儲(chǔ)引擎的具體工作機(jī)制很多時(shí)候?qū)﹂_(kāi)發(fā)工程師而言就是透明的,我們不需要關(guān)系 InnoDB 怎么工作的,寫(xiě)好自己的 SQL 就行(個(gè)別存儲(chǔ)引擎支持的 SQL 也有差異,這個(gè)另論),這樣對(duì)開(kāi)發(fā)工程師來(lái)說(shuō)是更加友好了。
好啦,今天就和小伙伴們先扯這么多~
參考資料:
- https://zhuanlan.zhihu.com/p/43736857
- https://juejin.cn/post/6857688351168954376
本文轉(zhuǎn)載自微信公眾號(hào)「江南一點(diǎn)雨」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系江南一點(diǎn)雨公眾號(hào)。