mysql原始碼關於鍊錶的實現在ut0lst.**件中,其設計思路與常規略有不同,基本思想是指標嵌於物件之內,如下圖所示。
在這種實現方式下,構造乙個鍊錶需要同時指定物件型別和物件內指標節點的位址。為什麼這麼複雜呢?我們對比一下c++11標準庫中list的實現,發現其就是乙個模板類,構造乙個list只需要傳入物件型別即可,這更符合我們的理解。研究了下原始碼,也沒找到這樣設計的合理之處。突然想起了mysql磁碟資料檔案的儲存格式,發現這種設計與其很相符。
簡單來說,mysql的資料檔案(其實就是乙個namespace)被分成了很多extent,每個extent包含64個page,也就是1m。那如何管理這些extent呢?沒256個extent分為一組,每組的第乙個page包含了256個extent_entry,每個entry包含64個page的狀態和乙個指標node,分別指向前後的entry,跟上面的圖是不是很像?
現在來說一下為什麼要這樣設計。在記憶體中,我們可以使用兩種設計方式:指標嵌於物件之內和物件嵌於節點之內。為什麼c++11中list的實現只需要傳入物件型別就可以呢?因為在**裡面我們可以直接通過符號來獲取prev和next指標的值,那你想想磁碟上面list能這樣做嗎?肯定不行了啊,在磁碟上面我們只能通過位址或偏移來獲取值。
其實上面說了這麼多,總結下來就是乙個問題:我們怎麼把list持久化到磁碟中?上面給出了一種很好的實現。
再延伸乙個問題:我們怎麼把b+tree持久化到磁碟中?mysql索引就是這麼幹的,具體可以在網上找下這方面的介紹。
為什麼不用c++11中list的實現?
以insert為例,首先我們要構造乙個物件,然後再insert,這裡面涉及到一次拷貝構造,降低了效率。(儘管是通過引用傳參,但insert函式要把這個物件拷貝到list中)那如果把物件的位址insert進去呢?物件的析構怎麼辦。正常使用pop_back或pop_front時會自動呼叫析構函式,如果物件是乙個指標,就存在析構的問題。
struct node {
node() {
cout << "construct." << endl;
node(const node &node) {
cout << "copy construct." << endl;
int main() {
list l;
l.push_back(node());
return 0;
output:
construct.
copy construct.
如果採用mysql的實現方案,可以直接在建構函式裡面把當前物件的位址加入到list中,不需要再insert,效率極高,並且這樣一來,我們只需要關注物件的建立,不需要關注list的更新。
mysql原始碼中關於sys_var的實現也是這種方式,每個sys_var中都會包含乙個next指標,用於串起整個sys_var,並用乙個all_sys_vars作為base節點。
mysql原始碼編譯表 MySQL原始碼編譯安裝
1 安裝cmake 2.8.10.2.tar.gz 以root使用者進入shell tar zxvf cmake 2.8.10.2.tar.gz cd cmake 2.8.10.2 configure make 無法make,檢測gcc編譯環境 make install 2 安裝ncurses 5....
mysql跨伺服器鍊錶 MySQL 原始碼鍊錶的實現
mysql 原始碼鍊錶的實現 mysql原始碼關於鍊錶的實現在ut0lst.件中,其設計思路與常規略有不同,基本思想是指標嵌於物件之內,如下圖所示。在這種實現方式下,構造乙個鍊錶需要同時指定物件型別和物件內指標節點的位址。為什麼這麼複雜呢?我們對比一下c 11標準庫中list的實現,發現其就是乙個模...
mysql原始碼公升級 MySQL原始碼公升級
mysql原始碼公升級 公升級的方法一般有兩類 1.利用mysqldump來直接匯出sql檔案,匯入到新庫中,這種方法是最省事兒的,也是最保險的,缺點的話,也顯而易見,大庫的mysqldump費時費力。2.直接替換掉mysql的安裝目錄和my.cnf,利用mysql upgrade 來完成系統表的公...