前言
我相信每一個程序員都避免不了和數據庫打交道,其中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默認引擎,鞏固自己的知識點。
掃一掃,關注我的公眾號