日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

作為一名 JAVA開發人員,寫 SQL 語句是常有的事,但是你知道 SQL 語句背后的處理邏輯嗎?比如下面這條 SQL 語句:

select * from user where id=1

執行完這條語句后,我們就會得到 id 為 1 的用戶信息。那么對于這一條 SQL 語句,MySQL服務器做了哪些處理呢?這篇文章我們就一起打卡 MySQL 數據庫中對 SQL 語句的處理邏輯。

了解 MySQL 數據庫的 SQL 語句內部處理邏輯有什么好處?當我們碰到 MySQL 的一些異常或者問題時,就能夠直戳本質,更為快速地定位并解決問題。

想要更好的了解 SQL 語句的內部處理邏輯,我們可以先看 MySQL 的基本架構圖,這樣我們可以站在更高的角度去俯瞰 MySQL 數據庫,MySQL 的基本架構示意圖如下:

select * from user 這條 SQL 語句,藏著哪些不可告人的秘密?

 

從圖中,我們可以清晰的看出 MySQL 的架構和各個模塊以及 SQL 語句的執行過程,MySQL 數據庫整體可以分為 Server 層和存儲引擎層兩部分,其中 Server 層是共有的,而存儲引擎層則是可以以插件的形式進行擴展。一條 SQL 語句大概會經歷鏈接管理、解析與優化、最后到存儲引擎,這三個模塊。接下來我們就來聊一聊這三個模塊。

連接管理

連接管理是 SQL 語句執行過程中碰到的第一關,鏈接管理就像一扇大門一樣,控制著客戶端與 Server 服務端的交互,連接管理主要工作是客戶端的身份認證和連接線程的管理。

每個客戶端與 Server 建立連接時,服務端都會創建一個線程來與客戶端進行交互,交互的第一項內容就是驗證客戶端的身份,認證憑據是基于客戶端發起連接請求時攜帶的主機信息、用戶名、密碼。如果認證失敗,則結束連接任務,并且返回的 Access denied for user 錯誤。

如果認證成功,連接管理還會做一件事情,到權限表中查詢出該用戶的權限,在這次連接下,后續的權限判斷都是基于此時讀取的權限為依據,也就是說連接成功后,即使管理員對這個用戶做了權限修改,也不會影響這次連接的權限驗證。

連接管理需要做的事情就比較簡單,主要是負責客戶端與服務端進行連接,當然在連接線程上,連接管理也做了優化,并不是每個客戶端執行完任務之后,就把該線程銷毀,連接管理會把這些線程緩存起來,等待新的連接,這也就不會頻繁的創建和銷毀線程,從而節約了開銷。

解析與優化

完成連接管理之后,SQL 語句執行的第二步就是解析和優化,這一步就非常的復雜,SQL 語句查詢的所有操作都在這里了。我們可以將這一步細分為 4 小步。

查詢緩存

在 MySQL 服務端也有緩存,這是一個非常雞肋的功能,為什么呢?看完了你就知道了。

MySQL 服務器拿到查詢請求后,會先到查詢緩存看看,之前是不是執行過這條語句。之前執行過的語句及其結果可能會以 key-value 對的形式,被直接緩存在內存中。key 是查詢的語句,value 是查詢的結果。如果你的查詢能夠直接在這個緩存中找到 key,那么這個 value 就會被直接返回給客戶端。如果語句不在查詢緩存中,就會繼續后面的執行階段。執行完成后,執行結果會被存入查詢緩存中。

看上去沒毛病,這樣做會大大提升 MySQL 的性能,然而,你想多了,MySQL 的查詢緩存命中率非常的低,主要原因是如果兩個查詢請求在任何字符上的不同(例如:空格、注釋、大小寫),都會導致緩存不會命中。

還有就是緩存有可能獲取到錯誤的數據,以某些系統函數舉例,可能同樣的函數的兩次調用會產生不一樣的結果,比如函數NOW,每次調用都會產生最新的當前時間,如果在一個查詢請求中調用了這個函數,那即使查詢請求的文本信息都一樣,那不同時間的兩次查詢也應該得到不同的結果,如果在第一次查詢時就緩存了,那第二次查詢的時候直接使用第一次查詢的結果就是錯誤的!

除了這些之外,MySQL 緩存的失效也非常的頻繁,MySQL的緩存系統會監測涉及到的每張表,只要該表的結構或者數據被修改,如對該表使用了 INSERT、 UPDATE、DELETE、TRUNCATE TABLE、ALTER TABLE、DROP TABLE 或 DROP DATABASE 語句,那使用該表的所有高速緩存查詢都將變為無效并從高速緩存中刪除!

看到這里你知道查詢緩存很雞肋了吧,緩存對 MySQL 數據庫來說弊大于利,所以在 MySQL 8.0 版本直接將查詢緩存的整塊功能刪掉了

語法解析和預處理

如果查詢緩存沒有命中,接下來就需要進入正式的查詢階段了。因為客戶端程序發送過來的請求只是一段文本而已,所以 MySQL 服務器程序首先要對這段文本做語法解析。

首先通過關鍵字將 SQL 語句進行解析,并且生成一個“解析樹”。MySQL 解析器將使用 MySQL 語法規則驗證和解析查詢,例如,關鍵字是否使用正確、關鍵字的順序是否正確或者引號是否前后匹配等。

預處理是根據一些 MySQL 規則進一步檢查解析樹是否合法,例如數據表和數據列是否存在,還會解析名字和別名,看看他們是否有歧義等。

查詢優化

語法解析和預處理之后,你的需求就明白了,需要查詢哪張表,查詢的數據列是哪些、條件是什么等等。但是使用怎么樣的方式是最優查詢方式呢?查詢優化就是來干這個事的,MySQL 的優化程序會對我們的語句做一些優化,如外連接轉換為內連接、表達式簡化、子查詢轉為連接等等。優化的結果就是生成一個執行計劃,這個執行計劃表明了應該使用哪些索引進行查詢,表之間的連接順序是啥樣的。

執行器

執行器會執行查詢優化后的執行計劃,通過與存儲引擎交互,完成數據的查詢操作,返回最終的數據結果。

開始執行的時候,要先判斷一下你對這個表 T 有沒有執行查詢的權限,如果沒有,就會返回沒有權限的錯誤,如下所示 (在工程實現上,如果命中查詢緩存,會在查詢緩存返回結果的時候,做權限驗證。查詢也會在優化器之前調用 precheck 驗證權限)。

mysql> select * from user where ID=1;

ERROR 1142 (42000): SELECT command denied to user 'b'@'localhost' for table 'T'

如果有權限,就打開表繼續執行。打開表的時候,執行器就會根據表的引擎定義,去使用這個引擎提供的接口。

比如我們這個例子中的表 user 中,假設 ID 字段沒有索引,那么執行器的執行流程是這樣的:

1、調用 InnoDB 引擎接口取這個表的第一行,判斷 ID 值是不是 10,如果不是則跳過,如果是則將這行存在結果集中;

2、調用引擎接口取“下一行”,重復相同的判斷邏輯,直到取到這個表的最后一行。

3、執行器將上述遍歷過程中所有滿足條件的行組成的記錄集作為結果集返回給客戶端。

到這里,執行 SQL 語句就執行完了,其實這內部還是非常復雜的。

存儲引擎

到上面為止,SQL 語句就執行完了,但是與真實數據打交道的是存儲引擎,存儲引擎是 MySQL服務器對數據的存儲和提取操作的封裝模塊。我們知道表是由一行一行的記錄組成的,但這只是一個邏輯上的概念,物理上如何表示記錄,怎么從表中讀取數據,怎么把數據寫入具體的物理存儲器上,這都是存儲引擎負責的事情。

為了實現不同的功能,MySQL提供了各式各樣的存儲引擎,不同存儲引擎管理的表具體的存儲結構可能不同,采用的存取算法也可能不同。比如,MySQL5.7 之后默認的 InnoDB 存儲引擎。

可以看出一條 SQL 語句的執行還是非常復雜的,涉及到了很多的模塊,文章到這里就結束了,感謝您的閱讀,希望這篇文章對你的學習和工作有所幫助,如果您覺得文章有用,歡迎點贊+轉發。

最后

覺得此文不錯的大佬們可以多多關注或者幫忙轉發分享一下哦,感謝!!!!

分享到:
標簽:select
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定