MySQL的基礎(chǔ)架構(gòu)

基礎(chǔ)架構(gòu)

MySQL的基礎(chǔ)架構(gòu)如下圖:

MySQL服務(wù)器邏輯架構(gòu)圖

大體來(lái)說(shuō),MySQL 可以分為 Server 層和存儲(chǔ)引擎層兩部分。

大多數(shù)的MySQL服務(wù)功能都在Server層,包括查詢解析、緩存、分析、優(yōu)化以及所有內(nèi)置函數(shù),所有跨存儲(chǔ)引擎的功能都在這一層實(shí)現(xiàn),比如存儲(chǔ)過(guò)程、觸發(fā)器、視圖等。

而存儲(chǔ)引擎則是負(fù)責(zé)存儲(chǔ)數(shù)據(jù),提供讀寫(xiě)接口。有多種存儲(chǔ)引擎,例如InnoDB、MyISAM等,各有各的優(yōu)勢(shì)和劣勢(shì),針對(duì)不同的應(yīng)用場(chǎng)景。最常用的是 InnoDB,在5.5.5版本以后, InnoDB是默認(rèn)引擎,也可以在創(chuàng)建表時(shí)使用“engine=存儲(chǔ)引擎”來(lái)指定特定的引擎。

存儲(chǔ)引擎不會(huì)解析SQL,但是InnoDB除外,它會(huì)解析外鍵定義,因?yàn)镾erver層沒(méi)有實(shí)現(xiàn)該功能。

連接器

我們?cè)诓樵償?shù)據(jù)之前,需要先連接 MySQL。我們可以通過(guò)以下命令連接數(shù)據(jù)庫(kù):

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

其中mysql 是客戶端工具,用來(lái)跟服務(wù)端建立連接。在完成TCP握手后,連接器開(kāi)始認(rèn)證你的身份,認(rèn)證基于用戶名、密碼和原始主機(jī)信息。如果使用SSL連接,還可以使用X.509證書(shū)認(rèn)證。如果用戶名或密碼出錯(cuò),則收到"Access denied for user"的錯(cuò)誤,認(rèn)證通過(guò)則連接器到權(quán)限表里面查出你擁有的權(quán)限,之后進(jìn)行的查詢都將依賴于此權(quán)限。也就是說(shuō),一個(gè)用戶成功建立連接后,即使你用管理員賬號(hào)這個(gè)用戶的權(quán)限做了修改,也不會(huì)影響已經(jīng)存在的連接的權(quán)限。

如果客戶端太久沒(méi)有動(dòng)作,則連接器會(huì)自動(dòng)將它斷開(kāi),這個(gè)時(shí)間是由參數(shù) wait_timeout 控制的,默認(rèn)值是8小時(shí),5.7 版本 斷開(kāi)后可以自動(dòng)重連。

由于建立連接是相對(duì)復(fù)雜的操作,所以我們一般會(huì)使用長(zhǎng)連接,但是 mysql 在執(zhí)行的過(guò)程中臨時(shí)使用的內(nèi)存是管理在連接對(duì)象中的,這些資源會(huì)等到連接斷開(kāi)才釋放。所以如果連接使用的時(shí)間過(guò)長(zhǎng),會(huì)導(dǎo)致內(nèi)存占用過(guò)高。在 MySQL 5.7 版本之后,可以通過(guò)mysql_reset_connection重新初始化連接資源,該命令會(huì)釋放資源,但是不需要重新連接和重新做權(quán)限驗(yàn)證。

但是現(xiàn)在開(kāi)發(fā)者并不需要注意在程序中是使用短連接或是長(zhǎng)連接了,而是將連接交由連接池管理。

查詢緩存

MySQL 拿到一個(gè)查詢請(qǐng)求后,如果查詢緩存是打開(kāi)的會(huì)先到查詢緩存看看,之前是不是執(zhí)行過(guò)這條語(yǔ)句。之前執(zhí)行過(guò)的語(yǔ)句及其結(jié)果MySQL將其放在一個(gè)引用表中,類(lèi)似 key-value 對(duì)的形式。key 是查詢的語(yǔ)句、當(dāng)前要查詢的數(shù)據(jù)庫(kù)、客戶端協(xié)議版本等等,value 是查詢的結(jié)果。如果你的查詢能夠直接在這個(gè)緩存中找到 key,那么這個(gè) value 就會(huì)被直接返回給客戶端(返回之前會(huì)驗(yàn)證權(quán)限)。

如果語(yǔ)句不在查詢緩存中,就會(huì)繼續(xù)后面的執(zhí)行階段。執(zhí)行完成后,執(zhí)行結(jié)果會(huì)被存入查詢緩存中。

但是只要對(duì)表進(jìn)行更新,那么該表相關(guān)的所有查詢緩存就會(huì)被清空。因此,如果更新頻繁的表,不建議進(jìn)行查詢緩存,除非是配置表這類(lèi)的,會(huì)比較適合使用查詢緩存。

在使用查詢緩存時(shí),需要注意的是 MySQL 中判斷緩存是否命中時(shí),并不會(huì)解析、或者格式化、參數(shù)化查詢語(yǔ)句(實(shí)際上,在檢查查詢緩存之前, MySQL 只做了一件事情,就是通過(guò)一個(gè)大小寫(xiě)不敏感的檢查看看 SQL 語(yǔ)句是否是以 SEL 開(kāi)頭的,以此來(lái)判斷是否是查詢語(yǔ)句),而是直接使用 SQL 語(yǔ)句和客戶端發(fā)送過(guò)來(lái)的其他原始信息與緩存 key 直接匹配,所以 SQL 語(yǔ)句上的任何不同都會(huì)導(dǎo)致緩存的不命中。不止如此,但查詢語(yǔ)句出現(xiàn)不確定的數(shù)據(jù)(任何用戶定義的函數(shù)、存儲(chǔ)函數(shù)、用戶變量、臨時(shí)表、mysql 庫(kù)中的系統(tǒng)表、任何包含列級(jí)別權(quán)限的表)時(shí),不會(huì)被緩存,例如:

DATA_SUB(CURRENT_DATE, INTERVAL 1 DAY) -- 不會(huì)被緩存
DATA_SUB('2020-3-22', INTERVAL 1 DAY) -- 會(huì)被緩存

將參數(shù) query_cache_type 設(shè)置成 DEMAND,這樣對(duì)于默認(rèn)的 SQL 語(yǔ)句都不使用查詢緩存。而對(duì)于你確定要使用查詢緩存的語(yǔ)句,可以用 SQL_CACHE 顯式指定,像下面這個(gè)語(yǔ)句一樣:

 select SQL_CACHE * from user;

查詢緩存默認(rèn)是開(kāi)啟的,可以關(guān)閉查詢緩存。

- 臨時(shí)的直接命令行執(zhí)行
set global query_cache_size=0
set global query_cache_type=0

- 永久的修改配置文件my.cnf ,添加下面的配置query_cache_type=0
query_cache_size=0

需要注意的是在 MySQL 8.0 版本,查詢緩存的整塊功能已經(jīng)被刪除了。

解析器

在執(zhí)行 SQL 前,需要先對(duì) SQL 語(yǔ)句進(jìn)行解析。

解析器先對(duì) SQL 語(yǔ)句做詞法分析,先識(shí)別出哪些是關(guān)鍵字,代表什么(將輸入轉(zhuǎn)化為一個(gè)個(gè) Token,然后分析哪些 Token 是關(guān)鍵字,哪些不是)。

然后再做語(yǔ)法分析,通過(guò)語(yǔ)法規(guī)則來(lái)驗(yàn)證和解析查詢,比如 SQL 中是否使用了錯(cuò)誤的關(guān)鍵字或者關(guān)鍵字的順序是否正確、及符號(hào)是否正確,并生成語(yǔ)法樹(shù)。

預(yù)處理器則會(huì)根據(jù) MySQL 規(guī)則進(jìn)一步檢查語(yǔ)法樹(shù)是否合法。比如檢查要查詢的數(shù)據(jù)表和數(shù)據(jù)列是否存在,解析名字和別名是否有歧義等等。

接下來(lái)預(yù)處理器還會(huì)驗(yàn)證權(quán)限(precheck)。

如果語(yǔ)句不對(duì),就會(huì)收到“You have an error in yourSQL syntax”的錯(cuò)誤提醒。一般語(yǔ)法錯(cuò)誤會(huì)提示第一個(gè)出現(xiàn)錯(cuò)誤的位置,所以你要關(guān)注的是緊接“use near”的內(nèi)容。

優(yōu)化器

通過(guò)解析器的解析后,優(yōu)化器就要對(duì)SQL語(yǔ)句進(jìn)行優(yōu)化。優(yōu)化器并不關(guān)心表使用的存儲(chǔ)引擎是什么,但是存儲(chǔ)引擎對(duì)于查詢優(yōu)化是有影響的,因?yàn)閮?yōu)化器會(huì)請(qǐng)求存儲(chǔ)引擎提供容量或是某個(gè)具體操作的開(kāi)銷(xiāo)信息以及表數(shù)據(jù)的統(tǒng)計(jì)信息,這些都會(huì)影響優(yōu)化器對(duì)查詢語(yǔ)句的優(yōu)化。

優(yōu)化器對(duì)查詢語(yǔ)句的優(yōu)化有,優(yōu)化多表關(guān)聯(lián)的時(shí)候,決定各個(gè)表的連接的順序;有多個(gè)索引的時(shí)候,決定使用哪個(gè)索引;還有重寫(xiě)查詢等等。

可以使用explain來(lái)查看執(zhí)行計(jì)劃,然后調(diào)整SQL語(yǔ)句、修改配置等等。

執(zhí)行器

優(yōu)化完 SQL 語(yǔ)句后便開(kāi)始執(zhí)行,先判斷一下是否有該表的查詢權(quán)限,沒(méi)有則返回沒(méi)有權(quán)限的錯(cuò)誤。(因?yàn)榭赡苓€有觸發(fā)器這種需要在執(zhí)行器階段才能確定的情況,預(yù)處理器的 precheck 是不能對(duì)這種運(yùn)行時(shí)才涉及到的表進(jìn)行權(quán)限校驗(yàn)的,所以需要在執(zhí)行時(shí)再進(jìn)行權(quán)限檢查。)

如果有權(quán)限,打開(kāi)表,然后調(diào)用存儲(chǔ)引擎的接口獲取數(shù)據(jù)返回。

本文介紹了MySQL的基礎(chǔ)架構(gòu),這也是一條SQL查詢語(yǔ)句執(zhí)行的流程。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • MYSQL 基礎(chǔ)知識(shí) 1 MySQL數(shù)據(jù)庫(kù)概要 2 簡(jiǎn)單MySQL環(huán)境 3 數(shù)據(jù)的存儲(chǔ)和獲取 4 MySQL基本操...
    Kingtester閱讀 8,060評(píng)論 5 115
  • 今天看到一位朋友寫(xiě)的mysql筆記總結(jié),覺(jué)得寫(xiě)的很詳細(xì)很用心,這里轉(zhuǎn)載一下,供大家參考下,也希望大家能關(guān)注他原文地...
    信仰與初衷閱讀 4,834評(píng)論 0 30
  • 轉(zhuǎn) # https://www.cnblogs.com/easypass/archive/2010/12/ 08/...
    呂品?閱讀 10,129評(píng)論 0 44
  • MYSQL應(yīng)該是最流行的WEB后端數(shù)據(jù)庫(kù)。大量應(yīng)用于PHP,Ruby,Python,Java 等Web語(yǔ)言開(kāi)發(fā)項(xiàng)目...
    smooth00閱讀 2,796評(píng)論 0 16
  • 一、MySQL優(yōu)化 MySQL優(yōu)化從哪些方面入手: (1)存儲(chǔ)層(數(shù)據(jù)) 構(gòu)建良好的數(shù)據(jù)結(jié)構(gòu)??梢源蟠蟮奶嵘覀僑...
    寵辱不驚丶?xì)q月靜好閱讀 2,654評(píng)論 1 8

友情鏈接更多精彩內(nèi)容