1. 程式人生 > >Berkeley DB 1.8.6原始碼學習(一)

Berkeley DB 1.8.6原始碼學習(一)

閱讀 Berdely DB 1.8.6 版。

基本資料結構

1、 資料庫

資料庫結構只含有兩個成員變數:

type DBTYPE 型別,用於標示資料庫使用的資料型別,為列舉型別,列舉值可以為 DB_BTREE, DB_HASH, DB_RECNO ,分別表示 B 樹、雜湊表、 RECNO 演算法;

internal void 型別指標,用於指向實際儲存資料的資料結構,就 B+ 樹來講,指向 B+ 樹結構;

資料庫的成員變數:

close :關閉資料庫;

del :刪除資料庫;

get :根據關鍵字獲取一條記錄;

put :寫入 / 更新一條記錄;

seq :順序遍歷;

sync :緩衝池與永久儲存器中的資料同步,即將資料寫入硬碟;

fd :獲取資料庫檔案描述符,記憶體資料庫沒有檔案描述符。

資料節點:資料節點用於在程式中傳遞關鍵字 / 資料的結構,有兩個成員變臉,

data void 型別指標,存放資料內容;

size size_t 型別, data 的長度;

B 樹基本資訊結構:含有 6 個成員變數和 2 個成員函式,記錄 B 樹的基本屬性。

flags :無符號 long 型別,表示資料庫是否支援多條記錄具備同一個關鍵字;

cachesize :無符號 int 型,可緩衝的位元組數;

maxkeypage int 型,每頁可含有最大鍵的個數;

minkeypage int 型,每頁必須含有鍵數量的最小值;

psize :無符號 int 型,頁面的大小;

lorder int 型,記錄機器的位元組順序,即大小端;

成員變數:

compare :鍵的比較函式;

prefix :鍵的字首比較函式,使用可以提高查詢的效能;

以上資料結構是 db.h 中的資料結構。

2、 緩衝池

緩衝池用於緩衝資料庫檔案在記憶體中的資料,以記憶體頁為單位;具有 8 個成員變數:

lqh lru Least Recently Used ,最近最久未使用演算法)佇列頭;

hqh :雜湊表;

curcache :當前緩衝頁的編號;

maxcache :緩衝頁的最大編號;

npages :資料庫檔案含有頁的數量;

pagesize :檔案頁的大小;

fd :資料庫檔案描述符;

pgcookie :指向具體的資料庫結構,譬如 B 樹;

2 個成員函式:

pgin :資料匯入時處理位元組大小端問題;

pgout :資料匯出時處理大小端問題;

頁面節點:頁面節點用於儲存頁面資訊,是緩衝池的 lqh hqh 操縱的物件,含有 5 個成員變數,

hq :雜湊佇列,用於連線的結構體;

q lru 佇列,用於連線的結構體;

page void 型別指標,指向頁面的實際記憶體地址;

pgno :頁面編號;

flags :頁面的狀態,已修改(需寫回)、正訪問、備使用;

以上資料結構是 mpool.h 中的資料結構。

3、 B

記憶體頁結構:用於記錄記憶體頁的資訊,位於頁面的開頭部分,含有 7 個成員變數:

pgno :頁面編號;

prevpg :左兄弟;

nextpg :右兄弟;

flags :頁面型別;

lower :空閒區低端指標;

upper :空想區高階指標;

linp :頁面儲存實際資料的索引起點;

關於記憶體頁需要關注其具體的部署,上述資料結構儲存於頁面的開始部分,從 linp 到頁面結束用於儲存實際的資料,同時這部分分為三個部分,靠近頁面開始的部分,即 linp 開始的部分是索引區,從頁面的最高階,即頁面結束的地址,向頁面開始方向是資料區,中間的部分是空閒區,空閒區使用 lower upper 劃定區間,即如果以 END 標示頁面的最高地址 結束地址,則 linp-- *lower )是索引區,( *lower -- *upper )是空閒區,( *upper --END 是資料區;當向頁面中寫入資料時,首先按照資料的大小在空閒區分配相應的區間,分配方式是將( *upper )向( *lower )方向移動待存入資料大小的空間,然後,將此事 upper 指向的地址記錄下來,即索引的值,這就需要為索引分配一個記憶體空間,分配的方式是將( *lower )向( *upper )方向移動存放地址的空間。如此完成了對儲存資料的分配,對資料的訪問通過 linp[] 即可取出對應的 index 的值,從而訪問需要的資料。至於訪問時如何知道資料的大小,資料的開始 4 個位元組構成的無符號整數記錄的資料的實際大小。

B 樹內部結點:有四個成員變數,

ksize :鍵的大小;

pgno :所在頁面的編號;

flags :儲存的資料型別,大資料、大鍵值;

bytes :具體資料的起始地址;

說明:在儲存時結點的後面就是資料的值,這樣一個結點實際佔有的記憶體就是被解構的大小加上 ksize 的值;

B 樹葉子結點:有四個成員變數,

ksize :鍵的大小;

dsize :資料的大小;

flags :資料型別,大資料、大鍵值;

bytes :儲存資料 / 鍵內容的起始地址;

說明:實際的內容接在上述結構的後面,首相存放的是鍵的值,之後存放的是資料的值,由於葉子結點中使用 ksize dsize 分別記錄鍵值和資料值的長度,所以不用擔心二者的定址,這樣葉子節點的大小就是結點的大小加上 ksize dsize

記錄定址結構:用於儲存傳遞記錄的定址資訊,含有兩個成員變數,

pgno :記錄所在頁面的編碼;

index :記錄在頁面中的位置;

說明:從上面頁面結構、內部結點結構和葉子結點結構的分析可知,一條記錄要麼指向一個頁面(內部結點),要麼就是實際的資料。

記錄定址結構 2 :含有兩個成員變數,

page :頁面指標;

index :記錄在頁面中的位置;

說明:與上一個結構使用的場合不同。

遊標:含有四個成員變數,

pg :遊標停留的頁面編號;

key :鍵值;

rcursor :遊標指向的記錄索引;

flags :遊標的狀態;

B 樹元資料結構:儲存 B 樹的元資料資訊,含有 6 個成員變數,

magic :魔數;

version :版本資訊;

psize :頁面大小;

free :空閒頁面連結串列,記錄第一個空閒頁面的編號;

nrecs

flags :樹性質,是否支援多條記錄只用相同的鍵,是否是 RECNO

說明:資料庫檔案的第 0 頁的開始部分存放著 B 樹元資料結構,本頁的剩餘部分空閒;

B 樹結構:

成員變數:

bt_mp :緩衝池;

bt_dbp :指向資料庫結構的指標;

bt_cur :當前正使用的頁面編號;

bt_pinned :正被其他函式使用的頁面;

bt_cursor :遊標;

bt_stack :訪問頁面的祖先結點棧;

bt_sp :棧指標;

bt_rkey :一些操作返回記錄暫時存放的鍵值;

bt_rdata :一些操作返回記錄暫時存放的資料值;

bt_fd :樹的檔案描述符;

bt_free :下一個空閒頁;

bt_psize :頁面大小;

bt_ovflsize :大資料的標準;

bt_lorder :位元組順序;

bt_order :順序遍歷方向:未設定、向後、向前;

bt_last :最近插入的頁面;

flags :樹的屬性,是否支援鎖功能等;

成員函式:

bt_cmp :鍵值比較函式;

bt_pfx :字首比較函式;