前言
我相信每一個程式設計師都避免不了和資料庫打交道,其中Mysql以其輕量、開源成為當下最流行的關係型資料庫。Mysql5.0以前以MyISAM作為預設儲存引擎,在5.5版本以後,以InnoDB作為預設儲存引擎,相比MyISAM,InnoDB完整的支援ACID事務特性,同時支援行級鎖,支援事務這一特性也決定了InnoDB代替MyISAM成為主流儲存引擎的一大決定性因素。
Mysql系統架構圖
mysql整體包含四大部分:
連線層:包含各種元件和連線互動介面(Connectors:各種語言可以操控SQL的基礎,支援各種語言)
核心層:也被稱作SQL Laye,包括安全、許可權、sql解析、快取、執行優化。我們常用的檢視、儲存過程、觸發器等功能的實現也集中在這一層
儲存引擎層:也被稱為Storage Engine Layer,由多種儲存引擎共同組成,負責儲存和獲取資料。伺服器是通過儲存引擎API來與它們互動的。MySQL中的儲存引擎可以實現外掛式管理,它提供了一系列標準的管理和服務支援。
系統層:實際儲存一些資料庫檔案以及日誌檔案等
Sql執行流程圖
連線層
如上圖(Sql執行流程)所示,我們Sql執行首先是客戶端向MySQL伺服器傳送一條查詢請求,與connectors互動,連線池認證相關處理。
- 半雙工通訊:Mysql客戶端/服務端通訊協議是一種
半雙工
的通訊通道,什麼叫半雙工
呢?半雙工
指的是允許客戶端和服務端雙方相互通訊,但是同一時刻只允許存在單向通訊。對於查詢sql來講,大多數都是客戶端傳送的查詢資料包較小且為單個資料包,服務端返回的資料包較大且較大時大多拆分為多個資料包,多個資料包都需要被客戶端完整接收才算是查詢結束,這也是為什麼在實際開發中要求我們避免使用select *
以及增加limlt
查詢條件的原因之一。 - Connectors(聯結器)的職責就是維護上述過程中的連線通到,包括建立連線、許可權表驗證、維持連線和關閉連線。新建和關閉應該不用過多描述;許可權表驗證是從
user、host、db
等表查出許可權,放置在連線的上下文中(也就是說已經開啟的連結不受許可權變更影響)。維持連線則指的是Connectors需要保障完全接收伺服器響應的資料包,不能出現丟包的情況。 - Connection Pool(連線池) :作為一個單程式多執行緒的應用,mysql連線也參照實現一種池化
對於mysql連線,任何時刻都有一個狀態,該狀態表示了mysql當前正在做什麼。使用show full processlist命令檢視當前狀態。下面是這些狀態的解釋:
- sleep:執行緒正在等待客戶端傳送新的請求;
- query:執行緒正在執行查詢或者正在將結果傳送給客戶端;
- locked:在mysql伺服器層,該執行緒正在等待表鎖。在儲存引擎級別實現的鎖,例如InnoDB的行鎖,並不會體現線上程狀態中。對於MyISAM來說這是一個比較典型的狀態。
- analyzing and statistics:執行緒正在收集儲存引擎的統計資訊,並生成查詢的執行計劃;
- copying to tmp table:執行緒在執行查詢,並且將其結果集複製到一個臨時表中,這種狀態一般要麼是做group by操作,要麼是檔案排序操作,或者union操作。如果這個狀態後面還有on disk標記,那表示mysql正在將一個記憶體臨時表放到磁碟上。
- sorting Result:執行緒正在對結果集進行排序。
- sending data:執行緒可能在多個狀態間傳送資料,或者在生成結果集,或者在想客戶端返回資料。
核心層
我們之前說過,核心層包括安全許可權(Management Services & Utilities 、)、sql解析(Parser)、快取(cache)、執行優化(Optimizer)四塊,不過還應該再加上SQL Interface(Sql介面),這一塊主要是承擔和連線層的互動的作用。所以歸納而言
名稱 | 說明 |
---|---|
Management Services & Utilities | MySQL 的系統管理和控制工具,包括備份恢復、MySQL 複製、叢集等。 |
SQL Interface(SQL 介面) | 用來接收使用者的 SQL 命令,返回使用者需要查詢的結果。 |
Parser(查詢解析器) | 包含驗證和解析兩部分,以便可以轉換為MySQL優化器可以識別的資料結構或返回 SQL 語句的錯誤。 |
Optimizer(查詢優化器) | 驗證許可權和優化查詢。舉個例子 SELECT id, name FROM student WHERE sex = "女"; ,SELECT 查詢先根據 WHERE 語句進行選取,而不是將表全部查詢出來以後再進行sex 過濾。這就屬於一種優化。SELECT 查詢先根據 id 和 name 進行屬性投影,而不是將屬性全部取出以後再進行過濾,將這兩個查詢條件連線起來生成最終查詢結果。所以說Mysql是使用“選取-投影-連線”策略進行查詢。 |
Caches & Buffers(查詢快取) | 查詢的時候如果發現快取中有(hash實現),就直接返回快取中的結果。這個快取機制是由一系列小快取組成的,比如表快取、記錄快取、key 快取、許可權快取等。 |
Caches & Buffers(查詢快取)
對select查詢結果做快取,這個快取可能包含多個小快取,快取的key值是通過查詢本身、當前要查詢的資料庫、客戶端協議版本號等一些可能影響結果的資訊計算得來。所以兩個查詢在任何字元上的不同 (例如 : 空格、註釋),都會導致快取不會命中。
MySQL 8.0版本中查詢快取的功能已經被刪除
Management Services & Utilities
主要為Mysql的管理服務和一些工具元件,主要作用是對資料的恢復、回滾,以及資料遷移、複製、後設資料的管理。主要為以下功能
- 資料庫備份和恢復
- 資料庫安全管理,如使用者及許可權管理
- 資料庫複製管理
- 資料庫叢集管理
- 資料庫分割槽,分庫,分表管理
- 資料庫後設資料管理
SQL Interface(SQL 介面)
主要是用來接收Sql資訊和返回執行結果.大體可以分以下幾類:
- Data Manipulation Language (DML).
- Data Definition Language (DDL).
- 儲存過程
- 檢視
- 觸發器
Parser(查詢解析器)
主要是對傳遞過來sql的分解,先對語法進行驗證檢查。語法檢查通過後,解析器會查詢快取,如果快取中有對應的語句,就直接返回結果不進行接下來的優化執行操作。
ps: 快取中資料被修改,會被清出快取。
Optimizer(查詢優化器)
Optimizer階段主要就是對sql的優化了,通過系統規則選定最優的執行方案。這個過程包括選擇語法、常量轉換與計算、無效程式碼排除、AND/OR等等,必要時還可能查詢儲存引擎,獲得最優策略。
Pluggable Storage Engine(儲存引擎層)
作為Mysql最具有特色的一塊地方,Mysql將儲存引擎作為一個抽象類,InnoDB、MyISAM、BDB、Memory等等都是其子類。5.5版本以後以InnoDB作為其預設實現。目前除mysql以外其他大多都是單一儲存引擎。
ps:儲存引擎是基於表的,而不是資料庫
InnoDB(預設儲存引擎)
- 完整的支援ACID事務
- 支援行級鎖
- 支援外來鍵
- 使用聚集索引,索引和資料綁在一起在一個邏輯空間上,b+樹葉子節點對於主鍵索引儲存的是資料,對於輔助索引(二級索引)對應的則是主鍵的值
- count掃全表
- 必須存在唯一索引(主鍵)
MyISAM
- 不支援事務,但是插入和更新更快
- 支援表級鎖
- 不支援外來鍵
- 使用非聚集索引,索引和資料分離的,b+樹葉子結點均儲存的是實體資料檔案地址的指標
- count走變數不走全表
- 唯一索引非必要
對於儲存引擎的分析在下一篇部落格會著重介紹,這裡先介紹整個Mysql的架構,通過架構可以反應出一個sql的執行流程
檔案系統層
磁碟最小單位是512位元組,作業系統是4KB,mysql裡最小的是page(頁面)有16K
因為基於儲存引擎的不同,底層檔案結構也會有些不同,比如InnoDB:frm是表定義檔案,ibd是資料檔案,而MyISAM:myd是資料檔案,myi是索引檔案。InnoDB還有redo Log、undo Log
結尾
本篇部落格作為一個Mysql全域性概覽的介紹,由連線層自上而下的說明了整個Mysql的結構組成,但是Mysql核心還是在儲存引擎上,所以後面會專門拿出一篇博文來介紹InnoDB預設引擎,鞏固自己的知識點。
掃一掃,關注我的公眾號