支持多種存儲引擎是眾所周知的MySQL特性,也是MySQL架構(gòu)的關(guān)鍵優(yōu)勢之一。如果能夠理解MySQL Server與存儲引擎之間是怎樣通過API交互的,將大大有利于理解MySQL的核心基礎(chǔ)架構(gòu)。本文將首先介紹MySQL的整體邏輯架構(gòu),然后分析MySQL的存儲引擎API并介紹如何編寫自己的MySQL存儲引擎。
MySQL邏輯架構(gòu)
MySQL作為一個大型的網(wǎng)絡(luò)程序、數(shù)據(jù)管理系統(tǒng),架構(gòu)非常復(fù)雜。下圖大致畫出了其邏輯架構(gòu)。
	
Connectors
MySQL首先是一個網(wǎng)絡(luò)程序,其在TCP之上定義了自己的應(yīng)用層協(xié)議。所以要使用MySQL,我們可以編寫代碼,跟MySQL Server建立TCP連接,之后按照其定義好的協(xié)議進(jìn)行交互。當(dāng)然這樣比較麻煩,比較方便的辦法是調(diào)用SDK,比如Native C API、JDBC、PHP等各語言MySQL Connector,或者通過ODBC。但通過SDK來訪問MySQL,本質(zhì)上還是在TCP連接上通過MySQL協(xié)議跟MySQL進(jìn)行交互。
Connection Management
每一個基于TCP的網(wǎng)絡(luò)服務(wù)都需要管理客戶端鏈接,MySQL也不例外。MySQL會為每一個連接綁定一個線程,之后這個連接上的所有查詢都在這個線程中執(zhí)行。為了避免頻繁創(chuàng)建和銷毀線程帶來開銷,MySQL通常會緩存線程或者使用線程池,從而避免頻繁的創(chuàng)建和銷毀線程。
客戶端連接到MySQL后,在使用MySQL的功能之前,需要進(jìn)行認(rèn)證,認(rèn)證基于用戶名、主機(jī)名、密碼。如果用了SSL或者TLS的方式進(jìn)行連接,還會進(jìn)行證書認(rèn)證。
SQL Interface
MySQL支持DML(數(shù)據(jù)操作語言)、DDL(數(shù)據(jù)定義語言)、存儲過程、視圖、觸發(fā)器、自定義函數(shù)等多種SQL語言接口。
Parser
MySQL會解析SQL查詢,并為其創(chuàng)建語法樹,并根據(jù)數(shù)據(jù)字典豐富查詢語法樹,會驗(yàn)證該客戶端是否具有執(zhí)行該查詢的權(quán)限。創(chuàng)建好語法樹后,MySQL還會對SQl查詢進(jìn)行語法上的優(yōu)化,進(jìn)行查詢重寫。
Optimizer
語法解析和查詢重寫之后,MySQL會根據(jù)語法樹和數(shù)據(jù)的統(tǒng)計(jì)信息對SQL進(jìn)行優(yōu)化,包括決定表的讀取順序、選擇合適的索引等,最終生成SQL的具體執(zhí)行步驟。這些具體的執(zhí)行步驟里真正的數(shù)據(jù)操作都是通過預(yù)先定義好的存儲引擎API來進(jìn)行的,與具體的存儲引擎實(shí)現(xiàn)無關(guān)。
Caches & Buffers
MySQL內(nèi)部維持著一些Cache和Buffer,比如Query Cache用來緩存一條Select語句的執(zhí)行結(jié)果,如果能夠在其中找到對應(yīng)的查詢結(jié)果,那么就不必再進(jìn)行查詢解析、優(yōu)化和執(zhí)行的整個過程了。
Pluggable Storage Engine
存儲引擎的具體實(shí)現(xiàn),這些存儲引擎都實(shí)現(xiàn)了MySQl定義好的存儲引擎API的部分或者全部。MySQL可以動態(tài)安裝或移除存儲引擎,可以有多種存儲引擎同時存在,可以為每個Table設(shè)置不同的存儲引擎。存儲引擎負(fù)責(zé)在文件系統(tǒng)之上,管理表的數(shù)據(jù)、索引的實(shí)際內(nèi)容,同時也會管理運(yùn)行時的Cache、Buffer、事務(wù)、Log等數(shù)據(jù)和功能。
MySQL 5.7.11默認(rèn)支持的存儲引擎如下:
mysql> show engines; +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ | Engine | Support | Comment | Transactions | XA | Savepoints | +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ | InnoDB | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES | | MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO | | MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO | | BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO | | MyISAM | YES | MyISAM storage engine | NO | NO | NO | | CSV | YES | CSV storage engine | NO | NO | NO | | ARCHIVE | YES | Archive storage engine | NO | NO | NO | | PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO | | FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL | +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
File System
所有的數(shù)據(jù),數(shù)據(jù)庫、表的定義,表的每一行的內(nèi)容,索引,都是存在文件系統(tǒng)上,以文件的方式存在的。當(dāng)然有些存儲引擎比如InnoDB,也支持不使用文件系統(tǒng)直接管理裸設(shè)備,但現(xiàn)代文件系統(tǒng)的實(shí)現(xiàn)使得這樣做沒有必要了。
在文件系統(tǒng)之下,可以使用本地磁盤,可以使用DAS、NAS、SAN等各種存儲系統(tǒng)。
存儲引擎API
MySQL定義了一系列存儲引擎API,以支持插件式存儲引擎架構(gòu)。API以Handler類的虛函數(shù)的方式存在,可在代碼庫下的./sql/handler.h中查看詳細(xì)信息,可在handler類的注釋中看到描述:
/** The handler class is the interface for dynamically loadable storage engines. Do not add ifdefs and take care when adding or changing virtual functions to avoid vtable confusion Functions in this class accept and return table columns data. Two data representation formats are used: 1. TableRecordFormat - Used to pass [partial] table records to/from storage engine 2. KeyTupleFormat - used to pass index search tuples (aka "keys") to storage engine. See opt_range.cc for description of this format. TableRecordFormat ================= [Warning: this description is work in progress and may be incomplete] The table record is stored in a fixed-size buffer: record: null_bytes, column1_data, column2_data, ... //篇幅原因,略去部分內(nèi)容。 */ class handler :public Sql_alloc { //篇幅原因,不列出具體代碼。讀者可直接在源碼文件./sql/handler.h中找到具體內(nèi)容。 }
下面我將分類描述部分存儲引擎API。
創(chuàng)建、打開和關(guān)閉表
通過函數(shù)create來創(chuàng)建一個table:
/** *name:要創(chuàng)建的表的名字 *from:一個TABLE類型的結(jié)構(gòu),要創(chuàng)建的表的定義,跟MySQL Server已經(jīng)創(chuàng)建好的tablename.frm文件內(nèi)容是匹配的 *info:一個HA_CREATE_INFO類型的結(jié)構(gòu),包含了客戶端輸入的CREATE TABLE語句的信息 */ int create(const char *name, TABLE *form, HA_CREATE_INFO *info);
通過函數(shù)open來打開一個table:
/** mode包含以下兩種 O_RDONLY - Open read only O_RDWR - Open read/write */ int open(const char *name, int mode, int test_if_locked);
通過函數(shù)close來關(guān)閉一個table:
int close(void);
對表加鎖
當(dāng)客戶端調(diào)用LOCK TABLE時,通過external_lock函數(shù)加鎖:
int ha_example::external_lock(THD *thd, int lock_type)
全表掃描
//初始化全表掃描 virtual int rnd_init (bool scan); //從表中讀取下一行 virtual int rnd_next (byte* buf);
通過索引訪問table內(nèi)容
//使用索引前調(diào)用該方法
int ha_foo::index_init(uint keynr, bool sorted) 
//使用索引后調(diào)用該方法
int ha_foo::index_end(uint keynr, bool sorted)
//讀取索引第一條內(nèi)容
int ha_index_first(uchar * buf);
//讀取索引下一條內(nèi)容
int ha_index_next(uchar * buf);
//讀取索引前一條內(nèi)容
int ha_index_prev(uchar * buf);
//讀取索引最后一條內(nèi)容
int ha_index_last(uchar * buf);
//給定一個key基于索引讀取內(nèi)容
int index_read(uchar * buf, const uchar * key, uint key_len,
                         enum ha_rkey_function find_flag)
事務(wù)處理
//開始一個事務(wù) int my_handler::start_stmt(THD *thd, thr_lock_type lock_type) //回滾一個事務(wù) int (*rollback)(THD *thd, bool all); //提交一個事務(wù) int (*commit)(THD *thd, bool all);
如何編寫自己的存儲引擎
在MySQL的官方文檔上,有對于編寫自己的存儲引擎的指導(dǎo)文檔,鏈接如下。
作為編寫自己存儲引擎的開始,你可以查看MySQL源碼庫中的一個EXAMPLE存儲引擎,它實(shí)現(xiàn)了必須要實(shí)現(xiàn)的存儲引擎API,可以通過復(fù)制它們作為編寫我們自己存儲引擎的開始:
sed -e s/EXAMPLE/FOO/g -e s/example/foo/g ha_example.h > ha_foo.h sed -e s/EXAMPLE/FOO/g -e s/example/foo/g ha_example.cc > ha_foo.cc
審核編輯:黃飛
- 
                                TCP
                                +關(guān)注關(guān)注 8文章 1417瀏覽量 82800
- 
                                MySQL
                                +關(guān)注關(guān)注 1文章 893瀏覽量 29079
原文標(biāo)題:MySQL的多存儲引擎架構(gòu)
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
0基礎(chǔ)學(xué)Mysql:mysql入門視頻教程!
初探Android系統(tǒng)整體架構(gòu)
XILINX FPGA 芯片整體架構(gòu)是如何構(gòu)成的
MySQL基礎(chǔ)架構(gòu)自動化測試分析
 
    
詳解MySQL的查詢優(yōu)化 MySQL邏輯架構(gòu)分析
 
    
MySQL數(shù)據(jù)庫:理解MySQL的性能優(yōu)化、優(yōu)化查詢
 
    
干貨:20個MySQL開源數(shù)據(jù)庫架構(gòu)設(shè)計(jì)原則
MySQL的底層原理和技術(shù)學(xué)習(xí)
SQLite和MySQL區(qū)別
適用于MySQL的dbForge架構(gòu)比較
 
    
 
           
        
 
         MySQL的整體邏輯架構(gòu)
MySQL的整體邏輯架構(gòu) 
                 
  
            
             
             
                 
             工商網(wǎng)監(jiān)
工商網(wǎng)監(jiān)
        
評論