一條SELECT查詢語句在數據庫里執行時都經歷了什么


每天都在跟 mysql 打交道,你知道執行一條簡單的 select 語句,都經歷了哪些過程嗎?

 

首先,mysql 主要是由 server 層和存儲層兩部分構成的。server 層主要包括連接器、查詢緩存,分析器、優化器、執行器。存儲層主要是用來存儲和查詢數據的,常用的存儲引擎有 InnoDB、MyISAM,MySQL 5.5.5版本后使用 InnoDB 作為默認存儲引擎。

 

連接器

連接器主要負責將 mysql 客戶端和服務端建立連接,連接成功后,會獲取當前連接用戶的權限。這里獲取到的權限對整個連接都有效,一旦連接成功后,如果使用管理員賬號對該用戶更改權限,當前連接中的擁有的權限保持不變,只有等到下次重新連接才會更新權限。

 

查詢緩存

連接成功后,即開始要正式執行 select 語句了,但是在執行查詢之前,mysql 會去看下有沒有該條語句的緩存內容,如果有緩存直接從緩存中讀取並返回數據,不再執行后面的步驟了,結束查詢操作。

 

如果沒有緩存則繼續往后執行,並將執行結果和語句保存在緩存中。

 

注意:在 mysql8 后已經沒有查詢緩存這個功能了,因為這個緩存非常容易被清空掉,命中率比較低。只要對表有一個更新,這個表上的所有緩存就會被清空,因此你剛緩存下來的內容,還沒來得及用就被另一個更新給清空了。

 

分析器

既然沒有查到緩存,就需要開始執行 sql 語句了,在執行之前肯定需要先對 sql 語句進行解析。分析器主要對 sql 語句進行語法和語義分析,檢查單詞是否拼寫錯誤,還有檢查要查詢的表或字段是否存在。

 

如果分析器檢測出有錯誤就會返回類似 "You have an error in your sql" 這樣的錯誤信息,並結束查詢操作。

 

優化器
通過分析器之后,mysql 就算是理解了你要執行的操作了。通常對於同一個 sql 語句,mysql 內部可能存在多種執行方案,比如存在多個索引時,該選擇哪個索引,多個表關聯查詢時,怎么確認各個表的連接順序。

 

這些方案的執行結果都一樣,但是執行效率不一樣,所以 mysql 在執行之前需要嘗試找出一個最優的方案來,這就是優化器的主要工作。但是 mysql 也會有選擇錯誤方案的時候,這里暫不細說,留到后面再解釋原因。

 

執行器

經過優化器選定了一個方案后,執行器就按照選定的方案執行 sql 語句。前面我們有講過,在連接器中會讀取當前用戶的權限,連接器中只是獲取權限而已,並沒有對權限進行判斷和校驗。

 

所以在執行器中,在執行語句之前會判斷權限,如果沒有對應的權限則會直接返回並提示沒有相關權限。

 

這里你可能會問,為什么不在連接器中就直接判斷權限呢,這里我覺得可能是因為 mysql 要查詢的表並不一定僅限於 sql 語句中字面上的那些表,有的時候可能需要經過分析器和優化器之后才能確定到底要怎么執行,所以權限校驗放在執行器中是有道理的。

 

注意如果是在前面的查詢緩存中查到緩存之后,也會在返回結果前做權限校驗的。

 

權限校驗通過之后,就繼續打開表,調用存儲引擎提供的接口去查詢並返回結果集數據。

 到這里,一條查詢 sql 語句就執行結束了。講的比較粗糙,只是一個大致的流程,其中每一步在 mysql 的底層實現都非常復雜,需要逐步的深入了解。

 

 

耿小廚已開通個人微信公眾號,想進一步溝通或想了解其他文章的同學可以關注我

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM