標籤:
在過去的一年中的資料庫相關的原始碼分析。前段時間分析levelDB實施和BeansDB實現,資料庫網路分析這兩篇文章非常多。他們也比較深比較分析,所以沒有必要重複很多勞力。MYSQL,當然主要還是資料庫儲存引擎,首先我還是從innodb這個最流行的開源關聯式資料庫引擎著手來逐步分析和理解。
我一般分析原始碼的時候都是從基礎的資料結構和演算法逐步往上分析。遇到不明確的地方,自己依照原始碼又一次輸入一遍並做相應的單元測試,這樣便於理解。對於Innodb這種大項目,也應該如此,以後我會逐步將詳細的細節和實現寫到BLOG上。我分析Innodb是以MySQL-3.23為藍本作為分析對象,然後再去比較5.6版本號碼的修改來做分析的。這樣做有個優點就是先理解相對基礎的代碼easy。在有了基本概念後再去理解最新的修改。下面是我對innodb基礎的資料結構和演算法的理解。
1.vectorinnodb的vector是個動態數組的資料結構。和c++的STL使用方法相似,值得一提的是vector的記憶體配置能夠通過函數指標來指定是從heap記憶體池堆上分配記憶體還是用OS內建的malloc來分配記憶體。記憶體 Clerk的結構為:
struct ib_alloc_t { ib_mem_alloc_tmem_malloc; //分配器的malloc函數指標 ib_mem_free_tmem_release; //分配器的free函數指標 ib_mem_resize_tmem_resize; //分配器的又一次定義堆大小指標 void* arg; //堆控制代碼,假設是系統的malloc方式,這個值為NULL<span style="white-space:pre"></span>};vector內部整合了排序功能函數。其排序的演算法是通過qsort(高速)來進行排序。vector記憶體結構:
2.記憶體listinnodb的list資料結構是個標準的雙向鏈表結構。ib_list_node_t其中有指向前一個node的prev和指向後一個node的next,list的記憶體配置能夠通過heap記憶體堆來分配,也能夠通過系統的malloc來分配。
就看是採用ib_list_create_heap來建立list愛是永ib_list_create來建立list。可是內部的ib_list_node_t的記憶體配置是通過heap來分配的。
ist的記憶體結構:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXVhbnJ4ZHU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >
3.FIFO-queueinnodb的FIFO queue是個多線程的訊息佇列。能夠有多個線程向queue中加入訊息,可有多個線程同一時候讀取queue中的訊息並進行處理。queue的mutex是保證同一時候僅僅有一個線程在操作(讀或者寫)queue的items鏈表,os_event是寫線程完畢後通知全部讀線程能夠進行queue的讀事件。也就是說,僅僅有向queue寫完畢一個訊息。才會發送event訊號給讀線程。queue的訊息緩衝區是採用ib_list_t來做儲存的。一般寫的時候寫在list的最後,而讀總是讀取list的第一個。
queue處理提供一直讀取到訊息為止的方法以外,也提供最長等待讀取訊息的方法。這樣讀取線程沒有必要一直等待訊息。能夠在等待一段時間後去處理其它的任務。其C結構定義例如以下:
struct ib_wqueue_t{ib_mutex_tmutex; /*相互排斥量*/ib_list_t*items; /*用list作為queue的載體*/os_event_tevent; /*訊號量*/};4.雜湊表innodb中的雜湊表的基本構造和傳統的雜湊表的構造是相似的,不同的就是innodb的雜湊表採用的是自己定義鏈式桶結構。而沒有採用每一個桶單元用傳統的list來做碰撞管理。由於這個特性。innodb中的雜湊表操作採用了一系列操作宏來做操作。這樣做的目的是為了能泛型的對雜湊表做操作,由於在innodb中,除了操作記憶體中的資料以外,還會操作隱射硬碟中的資料。下面是innodb的操作宏:
HASH_INSERT 插入操作 HASH_DELETE 刪除操作 HASH_GET_FIRST 擷取指定HASH key相應cell的第一個資料單元 HASH_GET_NEXT 擷取cell_node相應的下一個單元 HASH_SEARCH 尋找相應key的值 HASH_SEARCH_ALL 遍曆整個hash table並將每一個資料單元為參數運行ASSERTION操作 HASH_DELETE_AND_COMPACT 刪除操作而且最佳化和調整heap堆上的記憶體配置布局,使得heap效率更高 HASH_MIGRATE 將OLD_TABLE的資料單元合并到NEW_TABLE其中這些宏在調用的時候都會指定資料的類型和Next函數名。
innodb的雜湊表在多線程併發模式下也提供cell級粒度的鎖,有mutex類型的鎖。也有rw_lock類型的鎖。
在hash_create_sync_obj_func函數調用過程中,會建立一個n_sync_obj的鎖資料單元。n_sync_obj必須是2的N次方。也就是說假設n_sync_obj = 8, 雜湊表的n_cells = 19。那就至少兩個cell公用一個鎖。
這是其它雜湊表無法比擬的。下面是hash table的結構定義:
struct hash_table_t{enum hash_table_sync_ttype;/*hash table的同步類型*/ulintn_cells;/*hash桶個數*/hash_cell_t*array;/*hash桶數組*/#ifndef UNIV_HOTBACKUPulintn_sync_obj;union{ /*同步鎖*/ib_mutex_t*mutexes;rw_lock_t*rw_locks;}sync_obj;/*heaps的單元個數和n_sync_obj一樣*/mem_heap_t**heaps;#endifmem_heap_t*heap;ulintmagic_n;/*校正魔法字*/#endif};
5.小結Innodb還有其它的一些資料結構,比如最小堆,這些都是通用的封裝,也就不做過多的描寫敘述,在能夠去看看innodb的原始碼相關就能夠。innodb在定義資料結構的時候做了特殊的處理,比如對線程並發的控制。對記憶體配置的控制。
這樣做的目的是為了統一的管理。
innodb的代碼是C的。但支援C++。裡面並沒有使用STL這樣的傳統的資料結構和演算法,非常大程度上是適合性的問題。
據說MYSQL 5.7開始大量使用boost 和STL。
個人感覺STL還勉強。使用boost有點感覺闊步前進。
著作權聲明:本文博主原創文章,部落格,未經同意不得轉載。
MySQL列:innodb的原始碼的分析的基礎資料結構