Development Environment
Windows XP Profession,Visual Studio C++ 2005
Concept
1、 Berkeley DB是嵌入式數(shù)據(jù)庫系統(tǒng),支持幾乎所有的現(xiàn)代操作系統(tǒng)。
2、 由一個(gè)個(gè)文件組成,文件名為XXX.DB,一個(gè)文件中可以含有一個(gè)到多個(gè)DB。
3、 Berkeley DB不支持SQL、存儲(chǔ)過程和觸發(fā)器等關(guān)系數(shù)據(jù)庫的高級(jí)特性。
4、 Database(DBT)就相同于關(guān)系數(shù)據(jù)庫中的Table,它的key/data 對(duì)就相當(dāng)于關(guān)系數(shù)據(jù)表的主鍵和其它n-1列,因?yàn)槟憧梢栽?span lang="EN-US">data中存入任意類型的數(shù)據(jù),比如一個(gè)結(jié)構(gòu)體。
5、 游標(biāo)(Cursor,DBC),就是一個(gè)關(guān)于特定記錄的遍歷器,在處理多重記錄(duplicate record,多條記錄key相同,而data不同)時(shí)使用它尤為方便,且效率高(稱為bulk get,一次獲取一批記錄)。
6、 數(shù)據(jù)庫環(huán)境(DB_ENV),為Berkeley DB的高級(jí)特性,就是多個(gè)Database的包裝器,它提供諸如日志恢復(fù)、多線程、事務(wù)處理和高性能支持等服務(wù)。
7、 數(shù)據(jù)訪問算法(Database Access Method)——數(shù)據(jù)在硬盤上存儲(chǔ)和操作的方法。Berkeley DB支持B+樹、Hash、Recno和Queue算法。
Begin to Use Berkeley DB
添加Berkeley db的include目錄為Application的include路徑,添加其lib目錄為Application的lib引用路徑,這樣將Berkeley DB的lib和我們的Application編譯為一個(gè)程序,令其“嵌入”我們的程序中。
Choose Database Access Method
Access Method | Description | Choosing Occasion |
B+樹 | 關(guān)鍵字有序存儲(chǔ),并且其結(jié)構(gòu)能隨數(shù)據(jù)的插入和刪除進(jìn)行動(dòng)態(tài)調(diào)整。為了代碼的簡(jiǎn)單,Berkeley DB沒有實(shí)現(xiàn)對(duì)關(guān)鍵字的前綴碼壓縮。B+樹支持對(duì)數(shù)據(jù)查詢、插入、刪除的常數(shù)級(jí)速度。關(guān)鍵字可以為任意的數(shù)據(jù)結(jié)構(gòu)。 | 1、 當(dāng)Key為復(fù)雜類型時(shí)。 2、 當(dāng)Key有序時(shí)。 |
Hash | DB中實(shí)際使用的是擴(kuò)展線性HASH算法(extended linear hashing),可以根據(jù)HASH表的增長進(jìn)行適當(dāng)?shù)恼{(diào)整。關(guān)鍵字可以為任意的數(shù)據(jù)結(jié)構(gòu)。 | 1、 當(dāng)Key為復(fù)雜類型。 2、 當(dāng)數(shù)據(jù)較大且key隨機(jī)分布時(shí)。 |
Recno | 要求每一個(gè)記錄都有一個(gè)邏輯紀(jì)錄號(hào),邏輯紀(jì)錄號(hào)由算法本身生成。相當(dāng)于關(guān)系數(shù)據(jù)庫中的自動(dòng)增長字段。Recho建立在B+樹算法之上,提供了一個(gè)存儲(chǔ)有序數(shù)據(jù)的接口。記錄的長度可以為定長或不定長。 | 1、 當(dāng)key為邏輯記錄號(hào)時(shí)。 2、 當(dāng)非高并發(fā)的情況下。 |
Queue | 和Recno方式接近, 只不過記錄的長度為定長。數(shù)據(jù)以定長記錄方式存儲(chǔ)在隊(duì)列中,插入操作把記錄插入到隊(duì)列的尾部,相比之下插入速度是最快的。 | 1、 1、當(dāng)key為邏輯記錄號(hào)時(shí)。 2、 定長記錄。 3、 高并發(fā)的情況下。 |
Open Database
使用Db.open來打開一個(gè)數(shù)據(jù)庫。打開數(shù)據(jù)庫有多種方式,常用的有:
Open Flag | Description |
DB_CREATE | 如果數(shù)據(jù)庫不存在,則創(chuàng)建之。 |
DB_EXCL | 如果數(shù)據(jù)庫存在,則返回失敗。只和DB_CREATE一起使用才有意義。 |
DB_RDONLY | 以只讀的方式打開數(shù)據(jù)庫。 |
代碼示例:
#include <db_cxx.h> ... Db db(NULL, 0); // Instantiate the Db object u_int32_t oFlags = DB_CREATE; // Open flags; try { // Open the database db.open(NULL, // Transaction pointer "my_db.db", // Database file name NULL, // Optional logical database name DB_BTREE, // Database access method oFlags, // Open flags 0); // File mode (using defaults) // DbException is not subclassed from std::exception, so // need to catch both of these. } catch(DbException &e) { // Error handling code goes here } catch(std::exception &e) { // Error handling code goes here } |
如果需要使用Berkeley DB的高級(jí)功能,可以在DbEnv(環(huán)境)中打開Database:
#include <db_cxx.h> ... u_int32_t env_flags = DB_CREATE; // If the environment does not // exist, create it. u_int32_t db_flags = DB_CREATE; // If the database does not // exist, create it. std::string envHome("/export1/testEnv"); std::string dbName("mydb.db"); DbEnv myEnv(0); Db *myDb; try { myEnv.open(envHome.c_str(), env_flags, 0); myDb = new Db(&myEnv, 0); myDb->open(NULL, dbName.c_str(), NULL, DB_BTREE, db_flags, 0); } catch(DbException &e) { std::cerr << "Error opening database environment: " << envHome << " and database " << dbName << std::endl; std::cerr << e.what() << std::endl; exit( -1 ); } catch(std::exception &e) { std::cerr << "Error opening database environment: " << envHome << " and database " << dbName << std::endl; std::cerr << e.what() << std::endl; exit( -1 ); } |
Close Database
關(guān)閉數(shù)據(jù)庫很簡(jiǎn)單,只需要使用Db.close(0)來關(guān)閉db:
#include <db_cxx.h> ... Db db(NULL, 0); // Database open and access operations happen here. try { // Close the database db.close(0); // DbException is not subclassed from std::exception, so // need to catch both of these. } catch(DbException &e) { // Error handling code goes here } catch(std::exception &e) { // Error handling code goes here } |
當(dāng)在DbEnv中打開數(shù)據(jù)庫時(shí),關(guān)閉此DbEnv中的所有的Db后,必須關(guān)閉此DbEnv:
try { if (myDb != NULL) { myDb->close(0); } myEnv.close(0); } catch(DbException &e) { std::cerr << "Error closing database environment: " << envHome << " or database " << dbName << std::endl; std::cerr << e.what() << std::endl; exit( -1 ); } catch(std::exception &e) { std::cerr << "Error closing database environment: " << envHome << " or database " << dbName << std::endl; std::cerr << e.what() << std::endl; exit( -1 ); } |
在操作數(shù)據(jù)(添加、修改和刪除數(shù)據(jù))時(shí),都是在內(nèi)存中進(jìn)行的,并沒有寫到磁盤中,而只有當(dāng)我們調(diào)用Db.close(0)方法后,才將內(nèi)存中的數(shù)據(jù)寫入磁盤中。如果不想關(guān)閉數(shù)據(jù)庫而又想把數(shù)據(jù)寫入磁盤的話,可以調(diào)用Db.sync(0)方法,及時(shí)將數(shù)據(jù)寫入磁盤可以降低發(fā)生DB crash而導(dǎo)致數(shù)據(jù)丟失的危險(xiǎn)的幾率。