mysql是使用最廣泛的開源關係資料庫之一,大多數開發人員只會簡單的用sql語句操作數據,而不理解服務端架構和sql查詢語句在服務端的執行過程,本文會從sql語句執行路徑來介紹mysql服務端架構,包括連接器,查詢緩存,分析器,優化器等。 ...
mysql是最廣泛使用的開源資料庫之一,作為後端開發人員,或多或少都會和mysql打交道,本篇文章會從sql查詢語句的執行過程,來介紹mysql的伺服器架構,
查詢的過程大致分為從客戶端到伺服器,在伺服器上解析,生成執行計劃,執行,並返回結果給客戶端。如下圖1.1所示。
圖1.1 sql查詢執行路徑
1.1 連接器
連接器對客戶端的連接請求進行用戶名和密碼的驗證,並會管理連接池。客戶端和伺服器為“半雙工”通信協議,客戶端和伺服器無法同時發送消息,當伺服器向客戶端發送查詢結果時,必須全部返回,客戶端不能主動停止,mysql需要等所有的數據都發送給了客戶端才會釋放本次查詢所占用的資源,因此大多數庫函數都會接收結果並緩存在客戶端,以使查詢早點結束,減輕服務端壓力。
對於連接到mysql的客戶端,可以用show full processlist查看連接狀態,該狀態表示了mysql當前在做什麼,一個查詢完整的生命周期,狀態會變很多次。
在show full processlist中,欄位command表示線程正在執行的命令類型,The type of command the thread is executing,一般就是休眠(sleep),查詢(query),連接 (connect),含義如下:
- sleep,線程正在等待客戶端發送新的請求。
- query,線程正在執行查詢或將結果返回客戶端。
- connect,正在建立連接。
show full processlist最重要的欄位是state,Most states correspond to very quick operations. If a thread stays in a given state for many seconds,there might be a problem that needs to be investigated.An action, event, or state that indicates what the thread is doing,表示線程處於某一狀態下具體正在做什麼,值的含義如下:
- Locked,在Mysql伺服器層,線程正在等待鎖,這裡不包括innodb存儲引擎實現的行鎖
- Analyzing and statistics,線程正在收集存儲引擎的統計信息,並生成查詢的執行計劃。
- Copying to tmp table [on disk],線程正在執行查詢,並將結果放在臨時表,帶有on disk,表示mysql在將記憶體臨時表存入磁碟。
- Sorting result,線程正在對結果集排序。
- Sending data,線程正在多個狀態間傳送數據,或者在生成結果集,或者向客戶端返回數據。
1.2 查詢緩存
在解析sql語句之前,mysql會從查詢緩存中獲取數據,具體是一個大小寫敏感的哈希查找,sql語句必須和緩存中的sql語句完全匹配,否則不會命中,對於更新比較頻繁的資料庫,經常會導致緩存失效,建議將查詢緩存關閉。
1.3 分析器
假如查詢緩存沒有命中,則會進入分析器,對sql語句進行詞法和語法分析,並會進行預處理,以便知道此sql語句是要做什麼。它會驗證是否使用錯誤的關鍵字,關鍵字順序是否正確等。並且,預處理會根據一些規則對解析樹的合法性進行進一步校驗,比如檢查數據表和列是否存在,解析名字和別名,看看是否有歧義等,如下圖1.2經常遇到的語法錯誤就在這一階段
圖1.2 sql語法錯誤提示
1.4 優化器
sql語句經過分析器分析合法,需要經過查詢優化器轉化成執行計劃,查詢優化器解決的是怎麼做的問題,相同的sql語句,返回相同的結果集,有很多種執行方式,查詢優化器就是要選擇性能較好的一種。
mysql是基於成本的優化器,會預測一個查詢使用某種計劃時的成本,並選擇其中成本最小的一種,可以通過Last_query_cost值查詢到當前會話查詢的成本。很多原因會導致mysql優化器選擇錯誤的執行計劃,比如:統計信息不准、不考慮其他併發執行的查詢,執行計劃太多,無法估算所有的計劃等。
1.5 查詢執行引擎
查詢執行引擎根據優化器生成的執行計劃(執行計劃是一種數據結構,而不是位元組碼),調用存儲引擎介面,完成執行計劃中的所有操作。mysql將查詢結果返回客戶端是一個增量、逐步返回的過程。開始生成第一條結果,mysql就可以開始向客戶端返回數據。這樣做服務端無需存儲太多結果,減小了服務端記憶體的消耗壓力,另外,客戶端也可以第一時間獲得返回的結果。