Berkeley DB是一個開源的檔案資料庫,介於關係資料庫與記憶體資料庫之間,使用方式與記憶體資料庫類似,它提供的是一系列直接訪問資料庫的函式,而不是像關係資料庫那樣需要網路通訊、SQL解析等步驟。
基本介紹
- 外文名:Berkeley DB
- 類型:檔案資料庫
- 分類:開源
- 平台:UNIX/LINUX作業系統
簡介
結構
歷史
Berkeley DB對C、C++、Perl、Java、Python、Ruby、PHP等基本上所有的語言都提供了接口,對一條記錄只分為兩個欄位,一個為鍵,一個為值,鍵與值可以是任意的數據,並且可以長達4GB,它提供了四種數據存取算法:B+樹、Hash、Recno、Queue,根據不同數據類型,可以選擇適當的算法以達到最佳性能。
1991年,Berkeley DB的第一個版發行(Linux系統也是在這一年誕生)。
1992年,BSD UNIX第4.4發行版中包含了Berkeley DB1.85版。基本上認為這是Berkeley DB的第一個正式版。
1996年,Sleepycat軟體公司成立,提供對Berkeley DB的商業支持。
2006年,Sleepycat被Oracle收購,當前最新版本是4.7.25。
2009年,SUN被Oracle收購,不知道MySQL會不會再次啟用Berkeley DB。
特點
Berkeley DB 還擁有對一些老的UNIX資料庫,例如dbm, ndbm und hsearch的兼容接口.
對於在java系統中的使用,Berkeley DB提供了一個壓縮成jar單個檔案的java版本。 這個版本可以運行在java虛擬機上使用,並且擁有和C語言版本相同的所有操作和功能。
範例
函式使用
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
/* DB的函式執行完成後,返回0代表成功,否則失敗 */
void print_error(int ret)
{
if(ret != 0)
printf("ERROR: %s/n",db_strerror(ret));
}
/* 數據結構DBT在使用前,應首先初始化,否則編譯可通過但運行時報參數錯誤 */
void init_DBT(DBT * key, DBT * data)
{
memset(key, 0, sizeof(DBT));
memset(data, 0, sizeof(DBT));
}
void main(void)
{
DB *dbp;
DBT key, data;
u_int32_t flags;
int ret;
char *fruit = "apple";
int number = 15;
typedef struct customer
{
int c_id;
char name[10];
char address[20];
int age;
} CUSTOMER;
CUSTOMER cust;
int key_cust_c_id = 1;
cust.c_id = 1;
strncpy(cust. name, "javer", 9);
strncpy(cust.address, "chengdu", 19);
cust.age = 32;
/* 首先創建資料庫句柄 */
ret = db_create(&dbp, NULL, 0);
print_error(ret);
/* 創建資料庫標誌 */
flags = DB_CREATE;
/* 創建一個名為single.db的資料庫,使用B+樹訪問算法,本段代碼演示對簡單數據類型的處理 */
ret = dbp->open(dbp, NULL, "single.db", NULL, DB_BTREE, flags, 0);
print_error(ret);
init_DBT(&key, &data);
/* 分別對關鍵字和數據賦值和規定長度 */
key.data = fruit;
key.size = strlen(fruit) + 1;
data.data = &number;
data.size = sizeof(int);
/* 把記錄寫入資料庫中,不允許覆蓋關鍵字相同的記錄 */
ret = dbp->put(dbp, NULL, &key, &data,DB_NOOVERWRITE);
print_error(ret);
/* 手動把快取中的數據刷新到硬碟檔案中,實際上在關閉資料庫時,數據會被自動刷新 */
dbp->sync();
init_DBT(&key, &data);
key.data = fruit;
key.size = strlen(fruit) + 1;
/* 從資料庫中查詢關鍵字為apple的記錄 */
ret = dbp->get(dbp, NULL, &key, &data, 0);
print_error(ret);
/* 特別要注意數據結構DBT的欄位data為void *型,所以在對data賦值和取值時,要做必要的類型轉換。 */
printf("The number = %d/n", *(int*)(data.data));
if(dbp != NULL)
dbp->close(dbp, 0);
ret = db_create(&dbp, NULL, 0);
print_error(ret);
flags = DB_CREATE;
/* 創建一個名為complex.db的資料庫,使用HASH訪問算法,本段代碼演示對複雜數據結構的處理 */
ret = dbp->open(dbp, NULL, "complex.db", NULL, DB_HASH, flags, 0);
print_error(ret);
init_DBT(&key, &data);
key.size = sizeof(int);
key.data = &(cust.c_id);
data.size = sizeof(CUSTOMER);
data.data = &cust;
ret = dbp->put(dbp, NULL, &key, &data,DB_NOOVERWRITE);
print_error(ret);
memset(&cust, 0, sizeof(CUSTOMER));
key.size = sizeof(int);
key.data = &key_cust_c_id;
data.data = &cust;
data.ulen = sizeof(CUSTOMER);
data.flags = DB_DBT_USERMEM;
dbp->get(dbp, NULL, &key, &data, 0);
print_error(ret);
printf("c_id = %d name = %s address = %s age = %d/n",
cust.c_id, cust .name, cust.address, cust.age);
if(dbp != NULL)
dbp->close(dbp, 0);
}
游標使用
DBC * cur;
/* 首先打開資料庫,再打開游標 */
dbp->open(dbp, ……);
dbp->cursor(dbp, NULL, &cur, 0);
/* do something with cursor */
/* 首先關閉,在關閉資料庫 */
cur->c_close(cur);
dbp->close(dbp, 0);
Memset(&data, 0, sizeof(DBT));
/* 因為KEY和DATA為空,則游標遍歷整個資料庫記錄 */
While((ret = cur->c_get(cur, &key, &data, DB_NEXT)) == 0)
{
/* do something with key and data */
}
key.size = XXX;
While((ret = cur->c_get(cur, &key, &data, DB_SET)) == 0)
{
/* do something with key and data */
}
環境使用
DB_ENV *dbenv;
db_env_create(&dbenv, 0);
/* 在環境打開之前,可調用形式為dbenv->set_XXX()的若干函式設定環境 */
/* 通知DB使用Rijndael加密算法(參考資料4)對數據進行處理 */
dbenv->set_encrypt(dbenv, "encrypt_string", DB_ENCRYPT_AES);
/* 設定DB的快取為5M */
dbenv->set_cachesize(dbenv, 0, 5 * 1024 * 1024, 0);
/* 設定DB查找資料庫檔案的目錄 */
dbenv->set_data_dir(dbenv, "/usr/javer/work_db");
/* 打開資料庫環境,注意後四個標誌分別指示DB啟動日誌、加鎖、快取、事務處理子系統 */
dbenv->open(dbenv,home,DB_CREATE|DB_INIT_LOG|DB_INIT_LOCK| DB_INIT_MPOOL|DB_INIT_TXN, 0);
/* 在環境打開後,則可以打開若干個資料庫,所有資料庫的處理都在環境的控制和保護中。注意db_create函式的第二個參數是環境變數 */
db_create(&dbp1, dbenv, 0);
dbp1->open(dbp1, ……);
db_create(&dbp2, dbenv, 0);
dbp1->open(dbp2, ……);
/* do something with the database */
/* 最後首先關閉打開的資料庫,再關閉環境 */
dbp2->close(dbp2, 0);
dbp1->close(dbp1, 0);
dbenv->close(dbenv, 0);