湯敏麗
(凱里學院,貴州 凱里 556011)
基于MySQL數(shù)據(jù)庫的物理存儲格式的研究與解析
湯敏麗
(凱里學院,貴州 凱里 556011)
M ySQL數(shù)據(jù)庫是一個開源的數(shù)據(jù)庫.M ySQL以其小巧靈活著稱,其內(nèi)部代碼都是開源的,使用M ySQL不僅僅可以節(jié)約開發(fā)成本,而且還可以從開源的代碼中學到很多開發(fā)精髓.為了更好的了解mysql的物理存儲結(jié)構(gòu),我們直接研究了M ySQL數(shù)據(jù)庫的內(nèi)核代碼.本文主要是講解MySQL數(shù)據(jù)庫是物理存儲格式以及如何進行數(shù)據(jù)解析.
mysql;物理存儲格式;解析
隨著計算機開源技術(shù)的不斷發(fā)展,目前開發(fā)者越來越熱衷于使用開源軟件.基于開源的軟件的實現(xiàn)的所有代碼全部對外公開,且所有人員均可對開源軟件進行自定義的修改.這無疑是軟件開發(fā)界的福音.本文重點研究的MySQL數(shù)據(jù)庫也是開源的數(shù)據(jù)庫軟件.同樣,它的所有代碼也都是開源的.
MySQL數(shù)據(jù)庫是一種關(guān)系型數(shù)據(jù)庫管理系統(tǒng).它不是將所有數(shù)據(jù)存放到一個大倉庫內(nèi),而是將具有一定意義的數(shù)據(jù)相對獨立的存放到不同的表中.而表與表之間建立關(guān)聯(lián)關(guān)系.它由于其體積小,速度快,成本低等特點,成為很多中小型網(wǎng)站的絕佳選擇.MySQL是使用C/C++編寫的,并使用了多種編譯器進行測試,保證源代碼的可移植性.還可以處理擁有上千萬條記錄大型數(shù)據(jù)庫.
MySQL數(shù)據(jù)庫的一個顯著的特點就是插件式的表存儲引擎.它的好處是:每個存儲引擎都有各自的特點,能夠根據(jù)具體的應用建立不同的存儲引擎表.在windows下,默認使用InnoDB的數(shù)據(jù)存儲引擎.如果你的表只有*.frm文件,則存儲引擎是innodb.同樣,*.frm這個文件也是表定義文件,數(shù)據(jù)信息和索引信息放在ibdata1文件里.Ibdata1是InnoDB存儲引擎默認情況下的共享表空間文件,即所有的數(shù)據(jù)都放在這個表空間內(nèi).本文主要是針對MyISAM存儲引擎做解析.MySQL的體系結(jié)構(gòu)圖如圖1所示.
圖1 MySQL的體系結(jié)構(gòu)圖
安裝MySQL.打開mysql后輸入密碼.執(zhí)行如下的語句:
創(chuàng)建數(shù)據(jù)庫maqianli
mysql>Create database maqianli;
更改數(shù)據(jù)庫
mysql>Use maqianli;
創(chuàng)建表
mysql>create table mytest(t1 varchar(10),t2 varchar(10),t3 char(10),t4 varchar(10));
往表中插入數(shù)據(jù)
mysql>insert into mytest values('a','bb','bb','cc');
mysql>insert into mytest values('d','ee','ee','fff');
這樣我們會發(fā)現(xiàn)在MySQL的安裝路徑下data目錄下生成了一個maqianli的文件夾,mysql文件夾是系統(tǒng)安裝時默認生成的.在maqianli文件夾下有一個mytest.frm的文件.這個文件中記錄了mytest表結(jié)構(gòu)定義的信息.和data同層的有個ibdata1文件,里面記錄了表數(shù)據(jù)信息.我們生成的文件默認是InnoDB存儲引擎生成的,我們可以將其改變?yōu)镸yISAM存儲引擎.用如下語句
mysql>alter table mytest engine=myisam;
我們發(fā)現(xiàn)在MyISAM存儲引擎下,會生成如下三個文件.Frm擴展名結(jié)尾的是表定義文件.Myd擴展名結(jié)尾的是數(shù)據(jù)文件,myi擴展名結(jié)尾的是索引文件.
圖2 MyISAM存儲引擎生成的文件
3.2.1 下載MySQL源碼.下載地址是:http://www.mysql.com/downloads/mysql/文件名是mysql-5.5.12.tar.gz.
3.2.2 生成工程文件
安裝CMake軟件,下載地址是:http://www.cmake.org.然后安裝 Bison:下載地址是 http://gnuwin32.sourceforge.net/packages/bison.htm.安裝完成后,運行CMake.第一個edit里面選擇源文件目錄,第二個選擇要生成的目錄.下面的“Configur“e按鈕可以選擇你要生成的編譯環(huán)境的版本,我們選擇VC6作為我們的開發(fā)環(huán)境,然后點擊“Generate”就開始生成工程文件.這樣就生成了MySQL.dsw的工程,我們打開這個工程,然后搜索讀取frm文件的主要內(nèi)容及其其他相關(guān)代碼.
MyISAM存儲引擎一個表生成了3個文件,擴展名分別是.frm,.myd,.myi.Frm擴展名結(jié)尾的是表定義文件.Myd擴展名結(jié)尾的是數(shù)據(jù)文件,myi擴展名結(jié)尾的是索引文件.下面我們一一介紹三個文件的文件格式.
在源碼中我們能夠找到FRM創(chuàng)建文件的代碼,sql/table.cc,create_frm()里記錄了如何創(chuàng)建一個FRM文件的詳細過程.open_table_def函數(shù)是讀取frm表定義信息的函數(shù).其中調(diào)用了open_binary_frm函數(shù)是其主要的實現(xiàn)關(guān)鍵.該函數(shù)在sql able.cc文件里.函數(shù)原型如下:static int open_binary_frm(THD*thd,TABLE_SHARE*share,uchar*head,File file).在sql able.cc創(chuàng)建frm的文件的函數(shù)create_frm.函數(shù)原型如下:
create_frm(THD*thd,const char*name,const char*db,const char *table, uint reclength, uchar *fileinfo,HA_CREATE_INFO*create_info,uint keys,KEY*key_info)
下面我們羅列出FRM文件格式.由于文件中每個字節(jié)所代表的含義很多.所以我們只羅列關(guān)鍵字節(jié)含義.
表1 FRM文件格式
由上表我們可以看出,F(xiàn)RM文件里面存儲了MySQL版本,存儲引擎名,列等等信息.由于我們只是讀取表中字段,我們只需要關(guān)注相關(guān)信息即可.
表列信息:由表可以發(fā)現(xiàn),從2152開始記錄了表列頭信息.根據(jù)我們對照生成frm的原始文件和上表格式,發(fā)現(xiàn)2152記錄的是第一個列名的大小,緊接著記錄的是列名,其次空了三個字段又是列名大小+列名.如下所示:
圖3 MYTEST.FRM文件二進制格式-列信息
“06”表示的是sname的長度,后面的“05”表示的是ssex的長度.圖3中的2102處記錄了列數(shù).有了列數(shù),有了列信息,我們就很容易得讀出表的列信息.
表行信息:圖3中2168字節(jié)處記錄了表行的字段類型,由于一個表可能有很多列.每列的類型都有可能不同,所以結(jié)合圖3,讀源碼,和我們生成的原始文件做了如下分析:
圖4 MYTEST.FRM文件二進制格式-行信息
紅色標記的是記錄的字段大小信息,藍色標記記錄的是字段類型信息.我們創(chuàng)建表的時候sql語句是:create table info(sname char(3),ssex char(2),sclass char(3));可以看出sname是char型,大小為3.ssex是 char型,大小為 2,sclass是char型,大小為3.和我們剛分析的一致.
綜上所述,我們知道的信息有:列數(shù),列名,字段大小,字段類型.
MYI文件格式比較復雜,下面是一部分myi格式的信息,我們在讀文件的時候只使用了行數(shù)這個信息,讀myi文件的代碼我們直接用的是mysql的源碼:
我們讀源碼,得知在0033字節(jié)記錄了行數(shù)信息.源碼中保存在了MI_STATUS_INFO結(jié)構(gòu)體中的records成員里.MySQL讀寫MYI文件的函數(shù)在storagemyisammi_open.c文件里,函數(shù)原型分別是:
uchar*mi_state_info_read(uchar*ptr,MI_STATE_INFO*state);// 讀
uint mi_state_info_write(File file,MI_STATE_INFO*state,uint pWrite);// 寫
由于任務要求只讀出表字段便可,我們對這個文件的其他key信息沒有關(guān)注.僅僅通過MYI文件得到了行數(shù)信息.
表2 MYI文件格式
得到了上面所有的行列信息,下面我們開始根據(jù)這些信息,找到字段值信息.Myd文件可以分為固定大小字段格式和可變大小字段格式,目前我們只研究了固定格式的.可變大小字段格式的需要根據(jù)總大小和未使用大小信息相減得到所用的大小來讀取字段值.
由于myd需要根據(jù)數(shù)據(jù)類型的格式來確定每個字節(jié)的信息.下表我們只是羅列出第一列為int型,第二列為char型的格式.其他格式類似:
表3 myd文件格式
MySQL中支持很多種類型,這些類型在include/mysql_com.h里枚舉enum_field_types定義.每種類型所占用的字節(jié)數(shù)不同,int為4位,char為1位.Float為4位,double為8位等等.
我們讀取MYD文件的時候,跳過第一字節(jié)后就開始記錄字段值信息了.如果為int型,我們讀4個字節(jié)的信息,如果為char型,我們讀?。?*字段大?。┳止?jié)個信息.
本文我們主要分析了MySQL數(shù)據(jù)庫的物理存儲格式,由于MySQL是可插入的存儲引擎方式,本文重點研究了MyISAM存儲引擎的物理存儲格式.其他存儲引擎物理存儲格式的研究與本文方法類似,都是需要查看MySQL的開源代碼和相關(guān)文檔介紹.
〔1〕Baron Scbwartz,王小東,等.高性能 M ySQL(High Performance M ySQL).電子工業(yè)出版社,2010.
〔2〕張萍.M yISAM存儲引擎的分析與改進[A].全國第20屆計算機技術(shù)與應用學術(shù)會議(CACIS?2009)暨全國第1屆安全關(guān)鍵技術(shù)與應用學術(shù)會議論文集(下冊)[C].2009.
〔3〕鮑麗春.可插式數(shù)據(jù)存儲引擎:M ySQL走向企業(yè)級的保障[N].計算機世界,2007.
〔4〕姜承堯.MySQL技術(shù)內(nèi)幕-InnoDB存儲引擎.機械工業(yè)出版社,2011.
〔5〕顧治華,忽朝儉.MySQL存儲引擎與數(shù)據(jù)庫性能[J].計算機時代,2006(10).
〔6〕M ichael Kofler, 楊曉云, 等.MySQL5權(quán)威指南(The Definitive Guide to M ySQL5).人民郵電出版社,2006.
〔7〕馬永成,肖詩斌,王弘蔚,施水才.M ySql嵌入式存儲引擎的研究和實現(xiàn)[A].第三屆全國信息檢索與內(nèi)容安全學術(shù)會議論文集[C].2007.
TP3-05
A
1673-260X(2012)07-0028-03