Mysql系列(2)-mysql系統結構
一、資料庫模式
在資料模型中有型(Type)和值(Value)的概念。型就是某一類資料結構和屬性的說明,值就是具體的賦值。
模式:模式(Schema)是資料庫中全體資料的邏輯結構和特徵描述,是資料庫的型。
例項:模式的一個具體值稱為模式的一個例項(Instance),同一個模式可以有多個例項。
模式與例項的關係:
模式是相對穩定的,而例項是不斷變化的;模式反映的是資料的結構及其聯絡,而例項反映的是資料庫某一刻的狀態。
三級模式結構
- 資料庫系統由外模式、模式、內模式三級構成。
- 資料庫系統的三級模式是對資料的三個抽象級別,三級模式把資料的具體組織交給DBMS管理,使使用者不必關心資料在計算機當中如何表示,如何儲存,使用者可專注於資料的邏輯抽象。
1. 外模式
外模式(亦稱子模式或者使用者模式),是資料庫使用者能夠看到和使用的區域性資料的邏輯結構和特徵的描述。外模式保證了資料庫的安全性,每個使用者只能看到和訪問對應外模式中的資料,資料庫的其他資料對該使用者均不可見。
一般地,
- 外模式是模式的的子集,一個數據庫可以有多個外模式。
- 對模式中的同一資料,在外模式中也可以不同。
- 一個外模式可以被多個應用程式所使用,一個應用程式只能使用一個外模式。
DBMS提供子模式描述語言(子模式DDL)來嚴格定義子模式。
2. 模式
模式(亦稱邏輯模式)是資料庫全體資料的邏輯結構和特徵描述,是所用使用者的公共資料檢視。是資料庫系統結構的中間層,既不涉及資料的物理儲存細節,也不涉及具體的應用程式、開發工具和語言。
模式是資料庫在邏輯級的檢視,一個數據庫只有一個模式,定義模式時要考慮資料的邏輯結構和資料間的聯絡,定義資料的安全性和完整性。
DBMS提供模式描述語言(模式DDL)來嚴格定義模式。
3. 內模式
一個數據庫只有一個內模式(亦稱儲存模式),內模式是資料物理結構和儲存方式的描述,是資料庫中資料的內部表示方式。
DBMS提供內模式描述語言(內模式DDL)來嚴格定義內模式。
兩級映象
為了能夠在系統內部實現資料在3個抽象層次的聯絡和轉換DBMS在三級模式之間提供兩級映像功能:
- 外模式/模式映像
- 模式/內模式映像
其中外模式/模式映像保證了資料和程式之間的邏輯獨立性
1. 外模式/模式映像
模式描述資料的全域性邏輯結構,外模式描述資料的區域性邏輯結構。同一個模式可以有多個外模式,每一個外模式在資料庫系統中都有一個對應外模式/模式映像,它定義了外外模式與模式之間的對應關係。映像的定義通常包含在各自外模式的描述中。
當模式改變時,DBA可以對各個外模式/模式映像做相應的改變,從而使外模式保持不變,應用程式是依賴於外模式編寫的,所以應用程式可以不修改。所以說外模式/模式映像保證了資料和程式之間的邏輯獨立性。
2. 模式/內模式映像
資料庫模式和內模式都只有一個,因此模式/內模式映像也是唯一的,模式/內模式映像定義了資料全域性邏輯結構與儲存結構的對應關係。當資料庫的儲存方式發生變化時,由DBA對模式/內模式映像做相應的改變,可使模式保持不變,進而使外模式也保持不變,最後可達到應用程式不變的目的。所以說模式/內模式映像保證了資料和程式之間的物理獨立性
三級模式在RDBMS中的體現
- 外模式對應於檢視(View)和一部分基本表(Base Table),也就是檢視層;
- 模式對應於基本表(Base Table),也就是邏輯層;
- 內模式對應於儲存檔案(Stored File),物理層;
總結
在資料庫的三級模式中,模式是全域性的邏輯結構,它作為中間層獨立於其它兩層,在設計資料庫模式結構時要首先確定資料庫的邏輯結構。
資料庫的內模式依賴於它的模式(全域性邏輯結構),獨立於外模式,也獨立於具體的儲存裝置。它將模式定義的資料結構和聯絡按照一定的儲存策略進行組織,從而達到較好的時間和空間效率。
資料庫的外模式面向具體的應用程式,它定義在模式之上,因此可以獨立於儲存模式和儲存裝置。
資料庫的二級映像保證了資料庫外模式的穩定性,進而保證了依賴於特定外模式的應用程式的穩定性。一般情況下,只要應用程式的需求不變,應用程式就可以不用修改。
二、mysql資料庫系統結構
一、MySQL邏輯模組組成
Mysql可以看成是二層架構,第一層叫SQL Layer,這一部分主要功能是完成mysql資料庫系統處理底層資料之前的所有的準備工作,包括許可權判斷、sql解析、執行計劃優化、query cache的處理等; 第二層是儲存引擎層(Storage Engine Layer),這一層才是資料庫系統資料存取操作的實現,是由多種儲存引擎共同完成。
看起來結構簡單,但是每一層又包含很多的小模組。
SQL Layer層包含的模組有:
1. 初始化模組
初始化模組就是在mysql server啟動的時候,對整個系統做各種各樣的初始化操作,比如各種buffer,cache結構的初始化和記憶體空間的申請,各種系統變數的初始化設定,各種儲存引擎的初始化設定等
2. 核心API
核心API模組主要是為了提供一些需要非常高效的底層操作功能的優化實現,包括各種底層資料結構的實現,特殊演算法的實現,字元竄處理,數字處理等,小檔案I/O,格式化輸出,以及最重要的記憶體管理部分。核心API模組的所有原始碼都集中在mysys和strings資料夾下面。
3. 網路互動模組
底層網路互動模組抽象出底層網路互動所使用的介面api,實現底層網路資料的接收與傳送,以方便其它各個模組的呼叫。以及對這一程式的部分維護。所有原始碼都在vio資料夾下面。
4. Client & Server 互動協議模組
任何的C/S結構的軟體系統,都肯定會有自己獨有的資訊互動協議,MySQL也不例外,MySQL的Client & Server互動協議模組部分,實現了客戶端與MySQL互動過程中的所有協議。當然這些協議都是建立在現有的OS和網路協議之上的。如TCP/IP、Unix Socket.
5. 使用者模組
使用者模組所實現的功能,主要是包括使用者的登入連線許可權控制和使用者的授權管理。就像是MySQL的大門守衛一樣,決定是否給來訪者“開門”
6. 訪問控制模組
造訪客人進門了就可以想幹嘛就幹嘛麼? 為了安全考慮,肯定是不能如此隨意。這時候就需要訪問控制模組實時監控客人的每一個動作,給不同的客人以不同的許可權。訪問控制模組實現的功能就是根據使用者模組中各使用者的授權資訊,以及資料庫自身特有的各種約束,來控制使用者對資料的訪問。使用者模組和訪問控制模組兩者結合起來,組成了MySQL整個資料庫系統的許可權安全管理的功能。
7. 連線管理、連線執行緒、執行緒管理模組
連線管理模組負責監聽對MySQL Server的各種請求,接受連線請求,轉發所有連線請求到執行緒管理模組,每一個連線上MySQL Server的客戶端請求都會被分配(或建立)一個連線執行緒為其單獨服務。而連線執行緒的主要工作就是負責MySQL Server 與客戶端的通訊,接受客戶端的命令請求。傳遞Server端的結果資訊。執行緒管理模組則負責管理維護這些連線執行緒。還包括執行緒的建立,執行緒的cache等
8. Query解析和轉發模組
在MySQL中我們習慣將所有Client端傳送給Server端的命令都稱為query,在MySQL Server裡面,連線執行緒接受到客戶端的一個query後,會直接將該query傳遞給專門負責將各種Query進行分類然後轉發給相應的處理模組,這個模組就是Query解析和轉發模組。主要工作就是將query語句進行語義和語法分析,然後按照不同的操作型別進行分類,然後做出針對性的轉發。
9. Query Cache模組
Query Cache模組在MySQL中是一個非常重要的模組,他的主要功能是將客戶端提交給MySQL的select類的query請求的返回結果集cache到記憶體中,與該query的一個hash值做一個對應。該Query所取資料的基表發生任何資料的變化之後,MySQL會自動使該query的Cache失效。在讀寫比例非常高的應用系統中,Query cache對效能的提高是非常顯著的。當然他對記憶體的消耗也是巨大的。
10. Query優化器模組
Query優化器,就是優化客戶端請求的query,根據客戶端請求的query語句,和資料庫中的一些統計資訊,在一系列演算法的基礎上進行分析,得出一個最優的策略,告訴後面的程式如何取得這個query語句的結果。
11. 表變更管理模組
表變更管理模組主要負責完成一些DML和DDL的query,如:update、delete、insert、create table,alter table等語句的處理。
12. 表維護模組
表的狀態檢查,錯誤修復,以及優化和分析等工作都是表維護模組所需要做的事情。
13. 系統狀態管理模組
系統狀態管理模組負責在客戶端請求系統狀態的時候,將各種狀態資料返回給使用者,比如DBA常用的show status命令,show variables命令等,所得到的的結果都是由這個模組來返回的。
14. 表管理器
這個模組從名字上看來和上面的表變更和表維護模組相混淆,但是其功能與表變更及維護模組卻完全不同。大家都知道,每一個MySQL的表都有一個表的定義檔案,依舊是*.frm檔案。表管理器的工作主要就是維護這些檔案,以及一個cache,該cache中的主要內容是各個表的結構資訊。此外他還維護table級別的鎖管理。
15. 日誌記錄模組
主要負責整個系統級別的邏輯層的日誌的記錄,包括error log, binary log, show query log等。
16. 複製模組
複製模組又可分為Master模組和Slave模組兩部分,Master模組主要負責在Replication環境中讀取Master端binary日誌,以及與Slave端的I/O執行緒互動等工作。Slave模組比Master模組所要做的事情稍多一些。在系統中主要體現在兩個執行緒上面。一個是負責從Master請求和接受binary日誌,並寫入本地relay log中的I/O執行緒。另一個負責從relay log中讀取相關日誌檔案,然後解析成可以在Slave端正確執行並得到和Master端完全相同的結果的米寧再交給Slave執行的SQL執行緒。
17. 儲存引擎介面模組
儲存引擎介面模組是MySQL資料庫最有特色的一點了。目前各種資料庫產品中,基本上只有MySQL可以實現其底層資料儲存引擎的外掛式管理。這個模組實際上只是一個抽象類,但是正因為它成功的將各種資料庫處理高度抽象化,才成就了今天的MySQL可插拔儲存引擎的特色。
·可以看到僅第一層就擁有這麼多的模組,可見一個簡單易用的資料庫,其底層實現也超複雜的。
二、 各模組的工作配合
重點來了。 我們通過一個例子來闡述mysql系統的各個模苦是如何相親相愛的完成一個我們認為的很簡單的查詢工作的。
我們對啟動mysql,客戶端建立連線,請求query,得到返回結果,最終退出。這樣一整個過程來進行分析。
第一步:當我們執行啟動mysql系統的命令之後,mysql的初始化模組就從系統配置檔案中讀取系統引數和命令列引數,並按照引數來初始化整個系統,如申請並分配buffer,初始化全域性變數,以及各種結構等。同時各個儲存引擎也被啟動,進行各自的初始化工作。當整個系統初始化結束後,由連線管理模組接手,連線管理模組會啟動處理客戶端連線請求的監聽程式,包括tcp/ip的網路監聽,還有unix的socket,這時候,mysql serve就基本啟動完成,準備好接受客戶端的請求了。
第二步:當連線管理模組監聽到客戶端的連線請求(藉助網路互動模組的相關功能),雙方通過Client & Server互動協議模組所定義的協議“寒暄”幾句之後,連線管理模組就會將連線請求轉發給執行緒管理模組,去請求一個連線執行緒。
第三步:執行緒管理模組接著將控制權交給連線執行緒模組,告訴連線執行緒模組,現在我這邊連線請求過來了,需要建立連線,你趕快處理一下。連線執行緒模組會在接收到連線請求後,首先檢查當前連線執行緒池中是否有被cache的空閒連線執行緒,如果有,就取出一個和客戶端請求連線上,如果沒有空閒的連線執行緒,則建立一個新的連線執行緒與客戶端請求連線。當然,連線執行緒模組並不是在接收到連線請求後馬上就會取出一個連線執行緒和客戶端連線,而是首先通過呼叫使用者模組進行授權檢查,只有客戶端請求通過了授權檢查後,他才會將客戶端請求和負責請求的連線執行緒連上。
在MySQL中,將客戶端的請求分為了兩種型別,一種是query,需要呼叫Parser也就是Query解析和轉發模組的解析才能夠執行的請求;一種是command,不需要呼叫Parser就可以執行執行的請求。如果我們的初始化配置打開了Full Query Logging的功能,那麼Query解析與轉發模組就會呼叫日誌記錄模組將請求計入日誌。不管是一個Query型別的請求還是一個command型別的請求,都會被記錄進入日誌,所以出於效能考慮一般很少開啟Full Query Logging的功能。
第四步:當客戶端請求和連線執行緒“互換暗號(互通協議)”接上頭之後,連線執行緒就開始處理客戶端請求傳送過來的各種命令(或者query),接受相關請求。他將收到的query語句轉發給Query解析和轉發模組,Query解析器先對Query進行基本的語義和語法解析,然後根據命令型別的不同,有些會直接處理,有些會分發給其他模組來處理。
如果是一個Query型別的請求,會將控制權交給Query解析器,Query解析器首先分析是不是一個select型別的query,如果是,則呼叫查詢快取模組,讓它檢查該query在query cache中是否已經存在。如果有,則直接將cache中的資料返回給連線執行緒模組。然後通過與客戶端連線的執行緒將資料輸出給客戶端。如果不是一個可以被cache的query型別,或者cache中沒有改query的資料,那麼query將被繼續傳回Query解析器,讓Query解析器進行相應處理,在通過Query分發器分發給相關處理模組。
第五步:如果解析器解析結果是一條未被cache的select語句,則將控制權交給Optimizer,也就是Query優化器模組,如果是DML或者是DDL語句,則會交給表變更管理模組,如果是一些更新統計資訊、檢測、修復和整理類的query則會交給表維護模組去處理,複製相關的query則轉交給複製模組去進行相應的處理,請求狀態的query則交給狀態收集報告模組。實際上表變更管理模組根據所對應的處理請求的不同,是分別由insert處理器、delete處理器、update處理器、create處理器,以及alter處理器這些小模組來負責不同的DML和DDL的。
第六步:在各個模組收到Query解析與分發模組發過來的請求後,首先會通過訪問控制模組檢查連線使用者是否有訪問控制目標表以及目標欄位的許可權,如果有,就會呼叫表管理模組請求相應的表,並獲取對應的鎖。表管理模組首先會看到該表是否已經存在於table cache中,如果已經開啟則直接進行鎖相關的處理,如果沒有在cache中,則需要在開啟表文件獲取鎖,然後將開啟的表交給表變更管理模組。
第七步:當表變更管理模組“獲取”開啟的表之後,就會根據該表的相關meta資訊,判斷表的儲存引擎型別和其它相關資訊。根據表的儲存引擎型別,提交請求給儲存引擎介面模組,呼叫對應的儲存引擎實現模組,進行相應處理。
不過,對於表變更管理模組來說,可見的僅是儲存引擎介面模組提供的一系列“標準”介面,底層儲存引擎實現模組的具體實現,對於表變更管理模組來說是透明的。他只需要呼叫對應的介面,並指定表型別,介面模組會根據表型別呼叫正確儲存引擎來進行相應的處理。
第八步:當一條query或者是一個command處理完成(成功或者失敗)之後,控制權都會交還給連線執行緒模組。如果處理成功,則將處理結果(可能是一個Result set,也可能是成功或者失敗的標識)通過連線執行緒反饋給客戶端。如果處理過程中發生錯誤,也會將相應的錯誤資訊傳送給客戶端,然後連線執行緒模組會進行相應的清理工作,並繼續等待後面的請求,重複上面提到的過程,或者完成客戶端斷開連線的請求。
第九步:如果在上面的過程中,相關模組使資料庫中的資料發生了變化,而且MySQL打來了bin-log功能,則對應的處理模組還會呼叫日誌處理模組將相應的變更語句以更新事件的形式記錄到相關引數指定的二進位制日誌檔案中。
在上面各個模組的內容處理過程中,各自的核心運算處理功能部分都會高度依賴整個MySQL API模組,比如記憶體管理,檔案I/O,數字和字串處理等。
以上整個過程如下圖: