MySQL系列之一條SQL查詢語句的執行過程

極客時間《MySQL實戰》專欄的學習收穫html

最近剛剛購買了極客時間的課程《MySQL實戰45講》,我會在這裏將學習到的知識點作一個總結。mysql

本節主要是講MySQL的基礎架構。好比執行如下語句時:git

mysql> select * from T where ID=10;
複製代碼

這條語句在MySQL內部是如何處理的。github

基礎架構圖


如圖 主體分爲兩部分:Server和存儲引擎部分。

Server包括:鏈接器、緩存查詢、分析器、優化器、執行器。存儲過程、觸發器、視圖等功能都在Server層處理。sql

存儲引擎負責數據的存儲和提取。常見的有InnoDB、MyISAM。數據庫

鏈接器

鏈接器與客戶端創建鏈接、獲取權限、維持和管理鏈接。緩存

常見的命令:服務器

mysql -uroot -ppassword架構

用來和服務器創建鏈接,TCP握手後完成認證過程。post

  • 帳號密碼不對,報錯:"Access denied for user"
  • 認證經過,在權限表中查詢擁有的權限

只有在鏈接過程纔會從權限表中讀取權限信息,中途對權限的修改不會影響已經創建的鏈接,只有從新登錄後纔會使用新的權限信息。

創建鏈接後若是長時間處於空閒狀態,"show processlist" 命令能夠看到處處於sleep狀態的鏈接。
若規定時間內無活動,則會自動斷開鏈接。規定時間wait_timeout控制,默認爲8小時。斷開後,再次發請回會提示 "Lost connection to MySQL server during query" ,只能從新鏈接。

防止數據庫中出現佔用大量內存的狀況,能夠用一下方法解決:

  1. 按期斷開長鏈接或者佔用內存過大的鏈接。
  2. MySQL5.7及以上版本,每次執行一個較大的操做,可執行 "mysql_reset_connection"命令來初始化鏈接資源,該操做不會重連和從新獲取受權,只是恢復到剛創建鏈接的狀態。

查詢緩存

創建鏈接後,就能夠執行select操做,這是會執行第二部分:查詢緩存。

一個請求進來,首先查詢緩存,是否存在該記錄。以前執行過的語句,則會以語句爲key,執行後的結果集爲value存儲在內存中。

  • 若是在緩存中查找到,則回直接返回給客戶端。
  • 若是沒有找到記錄,繼續執行後面的操做,並將該語句與結果分別以key-value存入內存。

不建議使用查詢緩存,此操做弊大於利 ( MySQL8.0後將會刪除該功能 )

對於一個表,只要有更新便會將涉及到該表的緩存所有清空。
只適用於不常更新的靜態表
推薦:
-將query_cache_type 設置爲 DEMAND,默認SQL不使用查詢緩存,針對須要查詢緩存的語句,使用SQL_cache顯示指定,例如:

select SQL_CACHE * from T where ID = 10;
複製代碼

分析器

這條SQL要作什麼

  1. 詞法分析
    識別SQL關鍵字,提出主要成分。MySQL根據"select"得出這是一條查詢語句,根據"from T"識別表T,將"ID"識別爲列名。
  2. 語法分析
    根據語法規則判斷是否符合SQL的語法。若是出現錯誤,則提示:"You have an error in your SQL syntax...",後面是錯誤的地方,須要你關注"use naer"後的內容。

優化器

這條SQL如何作

這個步驟將會選取最優的執行方式,例如:

  1. 當涉及到多個索引時,決定用哪一個索引
  2. 多表關聯時,決定鏈接順序
    select * from t1 join t2 using(ID) where t1.c=10 and t2.d=20;
    複製代碼
    該步驟決定了先從t1表中取出c=10的ID值仍是先查找出t2表中d=20的ID值。

執行器

真正的執行步驟

根據鏈接器取到的權限判斷,是否對錶T有權限。

  • 如有權限,打開表繼續操做。

打開表後,根據表的引擎定義,使用引擎提供的接口。 例:

  • 表T中ID字段無索引:

    • 調用InnoDB提供的接口,取出第一行,當ID=10時,將該行數據放入結果集。若不符合則字啊次調用引擎接口獲取下一行,再次判斷,直至最後一行數據。
    • 將結果集存入緩存、返回給客戶端。
  • 表T中ID字段有索引:

    • 調用InnoDB的"獲取知足條件的第一行"接口,server層還會再判斷一次值是否正確,而後放入結果集,接着繼續訪問"知足條件的下一行"接口,這些接口是引擎已經定義好的。

在MySQL的慢查詢日誌中,rows_examined字段表示該語句執行過程當中掃描了多少行,這個值就是調用引擎獲取數據行的時候添加的。

某些場景下,執行器調用一次,引擎內部會掃描不少行,所以引擎掃描行數跟rows_examined並不徹底相同,這一點後文會詳細說明。


評論區知識點:

  • 問題:若是查詢語句中的字段不存在,會在哪一個階段報錯?

    • 答案:會在分析器階段報錯。
    • 《高性能MySQL》提到解析器和預處理器 解析器:處理語法和解析查詢,生成一顆對應的解析樹。 預處理器:進一步檢查解析樹的合法性,好比:數據表和數據列是否存在,別名是否有歧義等。若是經過則生成新的解析樹,在提交給優化器。
  • Connect_timeout 指的是「鏈接過程當中」的等待時間

  • wait_timeout指的是「鏈接完成後,使用過程當中」的等待時間

本文中含有極客時間《MySQL實戰》的圖和部分原文,若有侵權,請聯繫我馬上刪除
第二節:MySQL系列之一條更新SQL的生命歷程

相關文章
相關標籤/搜索