天天看點

mysql bdb_直接通路mysql的BDB存儲引擎

我們知道BDB是一種嵌入式的資料庫,存取效率比mysql高,但是管理起來沒有mysql友善,在分布式應用中同步也是一個問題。

恰好mysql是支援用BDB作為存儲引擎的(5.1之後就不直接支援了,因為BDB被oracle收購了),那麼能不能讓mysql來進行資料管理和同步,而實際應用則繞過mysql直接通路BDB檔案呢?

嘗試了一下:

首先取得mysql 5.0源代碼,按如下參數配置

./configure --with-berkeley-db=./bdb

編譯之後啟動mysql,建表時加上engine=bdb

此時在mysql的資料目錄中可以看見*.db檔案了。

用file指令檢視,發現檔案格式是Berkeley DB (Btree, version 9, native byte-order)

如果用db_dump指令檢視,可以發現它與普通的db檔案有兩處不同:

1. 一般的db檔案一個檔案中隻有一個庫,而mysql則生成了兩個庫,main和status庫(如果建表時加了主鍵之外的索引,則還會生成額外的索引庫)

2. mysql生成的db檔案,是以表的主索引作為key,用表的整行資料作為value,尤其對于char和varchar的列類型,mysql存儲時會在字元串前面加上字元長度。例如"abc"被存儲為"/x03abc"

對于第一點,可以在dbopen的時候指定一下庫名,對于mysql生成的db檔案,庫名指定為"main"就可以了。

對于第二點,在查詢時,需要把待查的key前面加上一個字元串長度,查出結果後,再把結果中的長度資訊剝離。

這裡面仍然存在一些問題,就是表結構的定義并不在db檔案中,而在mysql生成的.frm檔案裡。是以首先你不知道如何拆分字段,其次你不知道表長度的位元組是1個位元組還是兩個位元組或者更多。不過這個可以通過約定的方式解決,雙方約定好固定的表格式,可以将就一下。

但是更棘手的問題來了,做好這些改動後,發現查詢某些鍵值時,能查到結果,而某些鍵值就查不到結果。

原來,問題還是出在字元串前面的長度位元組上。一般來說,bdb的應用都使用字元串作為key,但是mysql存儲的時候,在字元串前面加了一個位元組,這就導緻了自定義比較函數的問題。

前面說了,檔案格式采用了Btree,那麼在插入一個key的時候,是會和根節點比較大小,然後決定去哪一個子樹。但是标準的比較大小是逐位元組的比較,而在字元串前面加上長度位元組後,相當于同長度的字元串會被劃到一棵子樹上去,也許mysql覺得這樣影響檢索效率,是以mysql通過自定義的比較函數,在比較字元串時把長度位元組去掉之後再比較。而使用标準的DBD的接口,它卻是按照标準的比較方式,自然會在很多情況下查找不到。

目前還沒有想到合适的解決方法,嘗試中……

--------------------------------------------

問題解決了,在bdb打開檔案之前,設定一個自定義的比較函數(DB->set_bt_compare),在比較函數中跳過第一個位元組,然後調用strncmp比較剩下的就行了。

至此圓滿解決直接通路mysql存儲引擎問題。