【譯】從草稿開始寫一個 MySQL 存儲引擎(一)

原文: Writing a MySQL storage engine from scratch

本文主要描述了如何寫一個MySQL 存儲引擎 - 一個可以持久保存 MySQL 表數據的插件

簡介

這篇文章總結了我在寫一個新的 MySQL 存儲引擎時學到的一些事情茂契。MySQL 的存儲引擎是一個能夠提供 在磁盤中存儲數據,并且能夠提供對數據的鏈接的插件篇梭。存儲引擎通常被作為 key/value 數據庫實現镐确,但是并不一定是這樣性穿。Oracle 的 MySQL 提供了多種存儲引擎结闸,并且所有的存儲引擎都能夠被重新編寫佣渴。默認的存儲引擎是 InnoDB剥险,一種 key/value 庫透硝。其他的存儲引擎有的能夠寫入 csv 文件(‘Tina’)或者專門用來歸檔數據('archive').Maria DB狰闪,作為一個分支,是一個更加先進并且提供了 Cassandra NoSQL 數據庫接口的存儲引擎濒生,Percona 的 TokuDB key/value 庫 和 xtradb埋泵,則是 InnoDB 的改進版本。

總的來說罪治,MySQL 有13種存儲引擎丽声,MariaDB 有大約20 種。但是這些仍然不夠觉义,讓我們再來添加一種雁社。

下載源碼以及第一次接觸

你能夠在 GitHub 上面下載 MySQL 的源碼,我的工作版本是 5.7.12晒骇。

git clone https://github.com/mysql/mysql-server.git

cd mysql-server

git checkout mysql-5.7-12

讓我們簡單看一下代碼的整體結構霉撵。文件和目錄的數量有點多,但是大部分和我們的工作無關洪囤,只有少部分的目錄值得我們仔細查看:

include 包含全局 include 文件徒坡,你能在里面找到 mysql.h,其中包含了很多重要的宏和聲明箍鼓。

sql 保護了 sql 相關的代碼:解析器,查詢引擎等呵曹。

sql/field.h Field class 描述了一個 MySQL 行款咖。

sql/item.h Item class 是一個解析器生成的抽象語法樹的節(jié)點。

sql/sql_*.cc 這些文件實現了實際上的 SQL 操作奄喂。

sql/handler.h 存儲引擎的基類

storage 這個目錄包含了所有的存儲引擎铐殃。

storage/innobase InnoDB 存儲引擎

storage/example 一個存儲引擎實例項目。

通過瀏覽這些代碼跨新,我們可以清晰地看出 mysql 代碼的基礎是相對較老的富腊。雖然大部分的代碼是通過 C++ 實現的,但是實際上僅僅是 “c 和 類”的實現方式域帐。更多的高級 c++ 特性赘被,例如 模板是整,exceptions 或者標準庫都沒有被使用。連接列表被實現成包裹在 "void *" 中的結構體對象(my_list.h)民假。mysql 還有它自己的 string 實現(string.c) 而不是使用 std::string浮入。RAII 也沒有被使用。更甚的是羊异,你能夠找到很多用于清理內存分配資源的 goto 語句事秀。

功能的實現會非常的長(超過 1000 行代碼,并且包含了多層的 if 語句 mysql_prepare_create_table)野舶,并且有一些類也非常的大易迹。很多方法被存儲在基類中而不是繼承類,并且類中存儲了很多的狀態(tài)平道。

MySQL 用了幾種內存自動分配(memroot_allocator.h)睹欲,它們不是標準的實現。很多類使用自己的內存分配來重寫了操作符 new 和 delete巢掺。

同時MySQL 的代碼沒有統一的編碼風格句伶。首行縮進都有多種風格,結構體的命名風格也有多種方式(陆淀。考余。。)轧苫,空格的使用也非常隨意(楚堤。。含懊。)身冬。

我沒有和 Oracle 或者 Mysql AB 工作的人討論過,但是我們可以基于這些代碼看出他們的合作風格岔乔。缺乏同一的代碼風格意味著每一位工程師都能選擇他最熟悉的方式酥筝。代碼風格有很大的差異,甚至在同一個文件中雏门,每個人也可以對任意部分的代碼進行修改嘿歌。我曾經在做過類似的工作,所以我明白這其中有非常多的工作需要做茁影。

如果 MySQL希望吸引新的開發(fā)者宙帝,“c 加 類”的使用,不使用標準庫并且非常長且復雜的功能實現都是需要重構的募闲。

編譯步脓,安裝,運行,debug

讓我們繼續(xù)安裝靴患。如果你運行了之前的步驟仍侥,那么接下來你需要檢查 mysql-server 目錄中的代碼。我們將在這個目錄中運行 cmake 來生成 Makefile蚁廓。我們同時將會創(chuàng)建一個 Debug build访圃,雖然它會有一點慢,但是在 debug 的過程中我們會用到它相嵌。

cd mysql-server

cmake -DCMAKE_BUILD_TYPE=Debug

make -j 5

sudo make install

你的編譯文件現在安裝在了 /usr/local/mysql 中腿时。你能通過在子目錄中運行 cmake 來生成獨立的 Debug 和 Release builds,并且你能夠選擇不同的安裝目錄饭宾,運行 “cmake --help”來獲得選項的列表批糟。在這個文章中我僅僅會保持所有事情盡可能簡單。

為了成功啟動 MySQL 客戶端看铆,我們還需要做以下事情徽鼎。我們需要創(chuàng)建一個數據目錄(用來存放 表)并且初始化它們(注意你可能需要改變下面代碼的文件路徑):

mkdir /home/alan/tmp/mysql-data # must be empty

cd /usr/local/mysql/bin

./mysqld --initialize --datadir=/home/alan/tmp/mysql-data

最后一個命令將會生成一個 root 密碼。記下它弹惦,接下來會用到否淤。我將我的開發(fā)環(huán)境設置為空的 root 密碼 - 在測試時它將會更加安全。你可以使用接下來的命令重新設置密碼(用上面生成的 root 密碼來替換 <PASSWORD>):

-- start the server

./mysqld --datadir=/home/alan/tmp/mysql-data

-- in a separate terminal we can now change the password

./mysqladmin password --user=root --password=<password>

</password>

然后我們可以創(chuàng)建一個新的數據庫:

./mysqladmin create test --user=root --password

客戶端能夠被正常啟動棠隐,并且之后你將可以創(chuàng)建表石抡,插入數據等等。

./mysql --user=root test

逐步構建一個新的存儲引擎

存儲引擎被實現為一個動態(tài)的庫(一個 .so 文件)助泽,并且他的源文件被存儲在 msyql-server/storage 目錄中啰扛。如果你僅僅希望玩一下那么你可以修改已有的 'example ' 存儲引擎。我選擇通過以下步驟創(chuàng)建我自己的 'upscaledb'嗡贺。

cd mysql-server/storage

-- copy the 'ha_example' directory to 'ha_upscaledb'

cp -r ha_example ha_upscaledb

-- rename the files

cd ha_upscaledb

mv ha_example.h ha_upscaledb.h

mv ha_example.cc ha_upscale.cc

最有一步就是隐解,使用你最喜歡的 IDE 來將 'example' 替換為 'upscaledb'以及 'EXAMPLE' 替換為 'UPSCALEDB'。不要忘記同樣更改你的 CMakeLists.txt 诫睬。然后進入 mysql-server 的根目錄并且再一次運行 'cmake' 和 ‘make’ 命令煞茫。新的 upscaledb 引擎現在構建好了,它的文件名是 mysql-server/storage/upscaledb/ha_upscaledb.so摄凡。

現在我們需要提示 MySQL 關于我們的新存儲引擎续徽。首先我們創(chuàng)建一個 安裝目錄 到新的 .so 文件的 symbolic link(軟連接?)架谎。通過這個連接我們的服務器將會總是使用最新版本的 .so 文件炸宵。不論我們何時修改了代碼辟躏,我們只需要簡單的重新編譯存儲引擎并且重啟 MySQL 服務器就行了谷扣。

cd /usr/local/mysql/lib/plugin

sudo ln -s ~/prj/msyql-server/storage/upscaledb/ha_upscaledb.so ha_upscaledb.so

最后的步驟就是更新 MySQL 的內部系統表。我們能夠使用 MySQL 的客戶端完成這些。同時確保 MySQL 的服務器端仍在運行会涎。

cd /usr/local/mysql/bin

./mysql --user=root test

mysql> INSTALL PLUGIN upscaledb SONAME 'ha_upscaledb.so';

現在你能夠使用最新的存儲引擎并且嘗試構建表 (create table test(value INTEGER) ENGINE=upscaledb;)」祝現在我們的存儲引擎只是一個框架并且沒有任何的實現。我們將會得到一個報錯末秃。在我們開始增添程序邏輯之前我會教你如何 Debug MySQL 服務器概页。接下來的代碼將會在 gdb 中啟動服務器,并且將會讓 gdb 獲取所有的信號练慕。(i.e. ctrl-c 可以結束 debugger)惰匙。

cd /usr/local/mysql/bin

gdb --args ./mysqld --gdb --datadir=/home/alan/tmp/mysql-data

嘗試在你的存儲引擎中的 'create()' 方法中設置一個斷點,并且運行一次上述的 CREATE TABLE 命令铃将。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末项鬼,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子劲阎,更是在濱河造成了極大的恐慌绘盟,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件悯仙,死亡現場離奇詭異龄毡,居然都是意外死亡,警方通過查閱死者的電腦和手機锡垄,發(fā)現死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進店門沦零,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人偎捎,你說我怎么就攤上這事蠢终。” “怎么了茴她?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵寻拂,是天一觀的道長。 經常有香客問我丈牢,道長祭钉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任己沛,我火速辦了婚禮慌核,結果婚禮上,老公的妹妹穿的比我還像新娘申尼。我一直安慰自己垮卓,他們只是感情好,可當我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布师幕。 她就那樣靜靜地躺著粟按,像睡著了一般诬滩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上灭将,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天疼鸟,我揣著相機與錄音,去河邊找鬼庙曙。 笑死空镜,一個胖子當著我的面吹牛,可吹牛的內容都是我干的捌朴。 我是一名探鬼主播吴攒,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼砂蔽!你這毒婦竟也來了舶斧?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤察皇,失蹤者是張志新(化名)和其女友劉穎茴厉,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體什荣,經...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡矾缓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了稻爬。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嗜闻。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖桅锄,靈堂內的尸體忽然破棺而出琉雳,到底是詐尸還是另有隱情,我是刑警寧澤友瘤,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布翠肘,位于F島的核電站,受9級特大地震影響辫秧,放射性物質發(fā)生泄漏束倍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一盟戏、第九天 我趴在偏房一處隱蔽的房頂上張望绪妹。 院中可真熱鬧,春花似錦柿究、人聲如沸邮旷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽婶肩。三九已至糕簿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間狡孔,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工蜂嗽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留苗膝,地道東北人。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓植旧,卻偏偏與公主長得像辱揭,于是被迫代替她去往敵國和親唧龄。 傳聞我的和親對象是個殘疾皇子叭莫,可洞房花燭夜當晚...
    茶點故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內容