青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆 - 3  文章 - 2  trackbacks - 0
<2025年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

常用鏈接

留言簿(1)

隨筆分類

隨筆檔案

文章分類

文章檔案

相冊

ACE資料

搜索

  •  

最新評論

閱讀排行榜

評論排行榜


[轉載]開源嵌入式數據庫Berkeley DB
開源嵌入式數據庫Berkeley DB
作者:肖文鵬 發文時間:2004.04.09

像MySQL這類基于C/S結構的關系型數據庫系統雖然代表著目前數據庫應用的主流,但卻并不能滿足所有應用場合的需要。有時我們需要的可能只是一個簡單的基于磁盤文件的數據庫系統。這樣不僅可以避免安裝龐大的數據庫服務器,而且還可以簡化數據庫應用程序的設計。Berkeley DB正是基于這樣的思想提出來的。

Berkeley DB簡介

Berkeley DB是一個開放源代碼的內嵌式數據庫管理系統,能夠為應用程序提供高性能的數據管理服務。應用它程序員只需要調用一些簡單的API就可以完成對數據的訪問和管理。與常用的數據庫管理系統(如MySQL和Oracle等)有所不同,在Berkeley DB中并沒有數據庫服務器的概念。應用程序不需要事先同數據庫服務建立起網絡連接,而是通過內嵌在程序中的Berkeley DB函數庫來完成對數據的保存、查詢、修改和刪除等操作。

Berkeley DB為許多編程語言提供了實用的API接口,包括C、C++、Java、Perl、Tcl、Python和PHP等。所有同數據庫相關的操作都由Berkeley DB函數庫負責統一完成。這樣無論是系統中的多個進程,或者是相同進程中的多個線程,都可以在同一時間調用訪問數據庫的函數。而底層的數據加鎖、事務日志和存儲管理等都在Berkeley DB函數庫中實現。它們對應用程序來講是完全透明的。俗話說:“麻雀雖小五臟俱全。”Berkeley DB函數庫本身雖然只有300KB左右,但卻能夠用來管理多達256TB的數據,并且在許多方面的性能還能夠同商業級的數據庫系統相抗衡。就拿對數據的并發操作來說,Berkeley DB能夠很輕松地應付幾千個用戶同時訪問同一個數據庫的情況。此外,如果想在資源受限的嵌入式系統上進行數據庫管理,Berkeley DB可能就是惟一正確的選擇了。

Berkeley DB作為一種嵌入式數據庫系統在許多方面有著獨特的優勢。首先,由于其應用程序和數據庫管理系統運行在相同的進程空間當中,進行數據操作時可以避免繁瑣的進程間通信,因此耗費在通信上的開銷自然也就降低到了極低程度。其次,Berkeley DB使用簡單的函數調用接口來完成所有的數據庫操作,而不是在數據庫系統中經常用到的SQL語言。這樣就避免了對結構化查詢語言進行解析和處理所需的開銷。

基本概念

Berkeley DB簡化了數據庫的操作模式,同時引入了一些新的基本概念,從而使得訪問和管理數據庫變得相對簡單起來。在使用Berkeley DB提供的函數庫編寫數據庫應用程序之前,有必要先了解以下這些基本概念。

關鍵字和數據

關鍵字(Key)和數據(Data)是Berkeley DB用來進行數據庫管理的基礎,由這兩者構成的Key/Data對(見表1)組成了數據庫中的一個基本結構單元,而整個數據庫實際上就是由許多這樣的結構單元所構成的。通過使用這種方式,開發人員在使用Berkeley DB提供的API來訪問數據庫時,只需提供關鍵字就能夠訪問到相應的數據。

Key Data?
sport football
Fruit orange
Drink beer


表1 Key/Data對

如果想將第一行中的“sport”和“football”保存到Berkeley DB數據庫中,可以調用Berkeley DB函數庫提供的數據保存接口。此時“sport”和“football”將分別當成關鍵字和數據來看待。之后如果需要從數據庫中檢索出該數據,可以用“sport”作為關鍵字進行查詢。此時Berkeley DB提供的接口函數會返回與之對應的數據“football”。

關鍵字和數據在Berkeley DB中都是用一個名為DBT的簡單結構來表示的。實際上兩者都可以是任意長度的二進制數據,而DBT的作用主要是保存相應的內存地址及其長度,其結構如下所示:

typedef struct {
? void *data;
? u_int32_t size;
? u_int32_t ulen;
? u_int32_t dlen;
? u_int32_t doff;
? u_int32_t flags;
} DBT;

?

在使用Berkeley DB進行數據管理時,缺省情況下是一個關鍵字對應于一個數據,但事實上也可以將數據庫配置成一個關鍵字對應于多個數據。

對象句柄

在Berkeley DB函數庫定義的大多數函數都遵循同樣的調用原則:首先創建某個結構,然后再調用該結構中的某些方法。從程序設計的角度來講,這一點同面向對象的設計原則是非常類似的,即先創建某個對象的一個實例,然后再調用該實例的某些方法。正因如此,Berkeley DB引入了對象句柄的概念來表示實例化后的結構,并且將結構中的成員函數稱為該句柄的方法。

對象句柄的引入使得程序員能夠完全憑借面向對象的思想,來完成對Berkeley DB數據庫的訪問和操作,即使當前使用的是像C這樣的結構化語言。例如,對于打開數據庫的操作來說,可以調用DB的對象句柄所提供的open函數,其原型如下所示:

int DB->open(DB *db, DB_TXN *txnid, const char *file,
const char *database, DBTYPE type, u_int32_t flags, int mode);

?

錯誤處理

對于任何一個函數庫來說,如何對錯誤進行統一的處理都是需要考慮的問題。Berkeley DB提供的所有函數都遵循同樣的錯誤處理原則,即函數成功執行后返回零,否則的話則返回非零值。

對于系統錯誤(如磁盤空間不足和訪問權限不夠等),返回的是一個標準的值;而對于非系統錯誤,返回的則是一個特定的錯誤編碼。例如,如果在數據庫中沒有與某個特定關鍵字所對應的數據,那么在通過該關鍵字檢索數據時就會出現錯誤。此時函數的返回值將是DB_NOTFOUND,表示所請求的關鍵字并沒有在數據庫中出現。所有標準的errno值都是大于零的,而由Berkeley DB定義的特殊錯誤編碼則都是小于零的。

要求程序員記住所有的錯誤代號既不現實也沒有什么實際意義,因為Berkeley DB提供了相應的函數來獲得錯誤代號所對應的錯誤描述。一旦有錯誤發生,只需首先調用db_strerror()函數來獲得錯誤描述信息,然后再調用DB->err()或DB->errx()就可以很輕松地輸出格式化后的錯誤信息。? 開源嵌入式數據庫Berkeley DB(2)?
作者:肖文鵬 發文時間:2004.04.09

接上一篇:開源的嵌入式數據庫Berkeley DB(1)

?

應用統一的編程接口

使用Berkeley DB提供的函數來進行數據庫的訪問和管理并不復雜,在大多數場合下只需按照統一的接口標準進行調用就可以完成最基本的操作。

打開數據庫

打開數據庫通常要分兩步進行:首先調用db_create()函數來創建DB結構的一個實例,然后再調用DB->open()函數來完成真正的打開操作。Berkeley DB將所有對數據庫的操作都封裝在名為DB的結構中。db_create()函數的作用就是創建一個該結構,其原型如下所示:

typedef struct__db DB;
int db_create(DB **dbp, DB_ENV *dbenv, u_int32_t flags);

?

將磁盤上保存的文件作為數據庫打開是由DB->open()函數來完成的,其原型如下所示:

int DB->open(DB *db, DB_TXN *txnid, const char *file,
const char *database, DBTYPE type, u_int32_t flags, int mode);

?

下面這段代碼示范了如何創建DB對象句柄及如何打開數據庫文件:

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <db.h>
#define DATABASE "demo.db"
/* 以下程序代碼的程序頭同此*/
int main()
{ DB *dbp;
int ret;
if ((ret = db_create(&dbp, NULL, 0)) != 0) {
? fprintf(stderr, "db_create: %s\n", db_strerror(ret));
? exit (1);
}
if ((ret = dbp->open(dbp, NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {
? dbp->err(dbp, ret, "%s", DATABASE);
? exit (1);
}
}

?

代碼首先調用db_create()函數來創建一個DB對象句柄。變量dbp在調用成功后將成為數據庫句柄,通過它可以完成對底層數據庫的配置或訪問。接下去調用DB->open()函數打開數據庫文件,參數“DATABASE”指明對應的磁盤文件名為demo.db;參數“DB_BTREE”表示數據庫底層使用的數據結構是B樹;而參數“DB_CREATE”和“0664”則表明當數據庫文件不存在時創建一個新的數據庫文件,并且將該文件的屬性值設置為0664。

錯誤處理是在打開數據庫時必須的例行檢查,這可以通過調用DB->err()函數來完成。其中參數“ret”是在調用Berkeley DB函數后返回的錯誤代碼,其余參數則用于顯示結構化的錯誤信息。

添加數據

向Berkeley DB數據庫中添加數據可以通過調用DB->put()函數來完成,其原型如下所示:

int DB->put(DB *db, DB_TXN *txnid, DBT *key, DBT *data, u_int32_t flags);

?

下面這段代碼示范了如何向數據庫中添加新的數據:

int main()
{ DB *dbp;
DBT key, data;
int ret;
if ((ret = db_create(&dbp, NULL, 0)) != 0) {
? fprintf(stderr, "db_create: %s\n", db_strerror(ret));
? exit (1);
}
if ((ret = dbp->open(dbp,
? NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {
? dbp->err(dbp, ret, "%s", DATABASE);
? exit (1);
}
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = "sport";
key.size = sizeof("sport");
data.data = "football";
data.size = sizeof("football");
if ((ret = dbp->put(dbp, NULL, &key, &data, 0)) == 0)
? printf("db: %s: key stored.\n", (char *)key.data);
else
? dbp->err(dbp, ret, "DB->put");
}

?

代碼首先聲明了兩個DBT結構變量,并分別用字符串“sport”和“football”進行填充。它們隨后作為關鍵字和數據傳遞給用來添加數據的DB->put()函數。DBT結構幾乎會在所有同數據訪問相關的函數中被用到。

在向數據庫中添加數據時,如果給定的關鍵字已經存在,大多數應用會對于已經存在的數據采用覆蓋原則。也就是說,如果數據庫中已經保存了一個“sport/basketball”對,再次調用DB->put()函數添加一個“sport/football”對,那么先前保存的那些數據將會被覆蓋。但Berkeley DB允許在調用DB->put()函數時指定參數“DB_NOOVERWRITE”,聲明不對數據庫中已經存在的數據進行覆蓋,其代碼如下:

if ((ret = dbp->put(dbp, NULL, &key, &data, DB_NOOVERWRITE)) == 0)
printf("db: %s: key stored.\n", (char *)key.data);
else
dbp->err(dbp, ret, "DB->put");

?

一旦給出“DB_NOOVERWRITE”標記,如果DB->put()函數在執行過程中發現給出的關鍵字在數據庫中已經存在了,就無法成功地把該Key/Data對添加到數據庫中,于是將返回錯誤代號“DB_KEYEXIST”。

檢索數據

從Berkeley DB數據庫中檢索數據可以通過調用DB->get()函數來完成,其原型如下所示:

int DB->get(DB *db, DB_TXN *txnid, DBT *key, DBT *data, u_int32_t flags);

?

下面這段代碼示范了如何從數據庫中檢索出所需的數據:

int main()
{ DB *dbp;
DBT key, data;
int ret;
if ((ret = db_create(&dbp, NULL, 0)) != 0) {
? fprintf(stderr, "db_create: %s\n", db_strerror(ret));
? exit (1);
}
if ((ret = dbp->open(dbp,
? NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {
? dbp->err(dbp, ret, "%s", DATABASE);
? exit (1);
}
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = "sport";
key.size = sizeof("sport");
if ((ret = dbp->get(dbp, NULL, &key, &data, 0)) == 0)
? printf("db: %s: key retrieved: data was %s.\n",
?? (char *)key.data, (char *)data.data);
else
? dbp->err(dbp, ret, "DB->get");
}

?

代碼同樣聲明了兩個DBT結構變量,并且調用memset()函數對它們的內容清空。雖然Berkeley DB并不強制要求在進行數據操作之前先清空它們,但出于提高代碼質量考慮還是建議先進行清空操作。在進行數據檢索時,對DB->get()函數的返回值進行處理是必不可少的,因為它攜帶著檢索操作是否成功完成等信息。下面列出的是DB->get()函數的返回值:

◆ 0 函數調用成功,指定的關鍵字被找到;

◆ DB_NOTFOUND 函數調用成功,但指定的關鍵字未被找到;

◆大于0 函數調用失敗,可能出現了系統錯誤。

刪除數據

從Berkeley DB數據庫中刪除數據可以通過調用DB->del()函數來完成,其原型如下所示:

int DB->del(DB *db, DB_TXN *txnid, DBT *key, u_int32_t flags);

?

下面這段代碼示范了如何從數據庫中刪除數據:

int main()
{ DB *dbp;
DBT key;
int ret;
if ((ret = db_create(&dbp, NULL, 0)) != 0) {
? fprintf(stderr, "db_create: %s\n", db_strerror(ret));
? exit (1);
}
if ((ret = dbp->open(dbp,
? NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {
? dbp->err(dbp, ret, "%s", DATABASE);
? exit (1);
}
memset(&key, 0, sizeof(key));
key.data = "sport";
key.size = sizeof("sport");
if ((ret = dbp->del(dbp, NULL, &key, 0)) == 0)
? printf("db: %s: key was deleted.\n", (char *)key.data);
else
? dbp->err(dbp, ret, "DB->del");
}

?

刪除數據只需給出相應的關鍵字,不用指明與之對應的數據。

關閉數據庫

對于一次完整的數據庫操作過程來說,關閉數據庫是不可或缺的一個環節。這是因為Berkeley DB需要依賴于系統底層的緩沖機制,也就是說只有在數據庫正常關閉的時候,修改后的數據才有可能全部寫到磁盤上,同時它所占用的資源也才能真正被全部釋放。關閉數據庫的操作是通過調用DB->close()函數來完成的,其原型如下所示:

int DB->close(DB *db, u_int32_t flags);

?

下面這段代碼示范了如何在需要的時候關閉數據庫:

int main()
{ DB *dbp;
DBT key, data;
int ret, t_ret;
if ((ret = db_create(&dbp, NULL, 0)) != 0) {
? fprintf(stderr, "db_create: %s\n", db_strerror(ret));
? exit (1);
}
if ((ret = dbp->open(dbp,
? NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {
? dbp->err(dbp, ret, "%s", DATABASE);
? goto err;
}
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = "sport";
key.size = sizeof("sport");
if ((ret = dbp->get(dbp, NULL, &key, &data, 0)) == 0)
? printf("db: %s: key retrieved: data was %s.\n",
?? (char *)key.data, (char *)data.data);
else
? dbp->err(dbp, ret, "DB->get");
if ((t_ret = dbp->close(dbp, 0)) != 0 && ret == 0)
? ret = t_ret;
exit(ret);
}

?

小結

Berkeley DB這個嵌入式數據庫系統使用非常簡單。它沒有數據庫服務器的概念,也不需要復雜的SQL語句,所有對數據的操作和管理都可以通過函數調用來完成,非常適合于那些需要對數據進行簡單管理的應用場合。

?

?

posted on 2006-12-14 10:22 Sword.Hell blog 閱讀(372) 評論(0)  編輯 收藏 引用 所屬分類: 使用Berkeley DB

只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产一二精品视频| 亚洲自拍都市欧美小说| 亚洲夜间福利| 亚洲一区二区动漫| 亚洲欧美日韩在线| 久久经典综合| 欧美福利小视频| 91久久国产综合久久| 欧美激情bt| 一区二区高清视频| 香蕉av福利精品导航| 99v久久综合狠狠综合久久| 亚洲毛片在线看| 午夜宅男久久久| 免费亚洲电影在线观看| 亚洲精品一区二区三区在线观看| 亚洲一级网站| 欧美成人免费网| 国产精品一区在线观看你懂的| 国产专区精品视频| 亚洲视频1区| 免费av成人在线| 宅男噜噜噜66一区二区| 久久资源av| 国产欧美亚洲视频| 一区二区三区三区在线| 久久综合99re88久久爱| 亚洲日本乱码在线观看| 欧美一区激情视频在线观看| 欧美激情无毛| 激情欧美日韩| 午夜影视日本亚洲欧洲精品| 久久婷婷av| 亚洲欧美精品伊人久久| 欧美成人一品| 在线播放日韩欧美| 久久精品欧美日韩精品| 在线视频精品一区| 欧美激情1区2区3区| 韩国女主播一区二区三区| 亚洲欧美日韩直播| 一本大道久久精品懂色aⅴ| 米奇777在线欧美播放| 国产在线视频不卡二| 午夜精品福利电影| 日韩一二三在线视频播| 欧美国产日韩xxxxx| 91久久精品国产91性色tv| 久久蜜桃av一区精品变态类天堂| 这里只有视频精品| 欧美日韩成人在线观看| 亚洲精品综合久久中文字幕| 亚洲成在人线av| 欧美www在线| 亚洲精品女人| 日韩视频一区| 国产精品激情av在线播放| 亚洲免费小视频| 亚洲欧美日韩另类精品一区二区三区| 国产精品久久久久久久第一福利 | 日韩亚洲成人av在线| 欧美高清视频一区| 亚洲精品久久久久久久久久久久久 | 一区在线观看视频| 久久夜色精品国产欧美乱| 欧美一区二区大片| 国产一级久久| 美女视频黄a大片欧美| 久久午夜视频| 亚洲美女电影在线| 夜夜精品视频一区二区| 国产精品美女久久久久aⅴ国产馆| 亚洲欧美综合| 欧美伊人久久久久久午夜久久久久 | 亚洲综合99| 亚洲在线一区二区| 韩国成人福利片在线播放| 欧美v日韩v国产v| 欧美mv日韩mv国产网站app| 日韩午夜三级在线| 亚洲午夜激情| 好吊妞这里只有精品| 欧美黄色影院| 国产精品第一页第二页第三页| 欧美亚洲综合在线| 老司机亚洲精品| 亚洲小说春色综合另类电影| 久久不见久久见免费视频1| 亚洲精品无人区| 午夜国产精品视频| 亚洲人在线视频| 亚洲欧美国产三级| 亚洲精品乱码久久久久| 亚洲一区二区精品视频| 亚洲福利视频一区二区| 一二美女精品欧洲| 亚洲国产日韩一级| 亚洲欧美日韩天堂| 日韩天堂在线视频| 久久久久久久97| 午夜精品视频在线| 欧美精品日韩三级| 美女91精品| 国产日本欧美一区二区三区在线 | 亚洲欧美激情视频在线观看一区二区三区 | 在线观看欧美亚洲| 夜夜嗨av一区二区三区网站四季av| 国产午夜精品在线观看| 99国产精品久久| 亚洲精品久久久久中文字幕欢迎你| 欧美一级播放| 欧美一区二区三区精品电影| 欧美日韩在线直播| 亚洲麻豆一区| 久久久美女艺术照精彩视频福利播放| 亚洲一区在线播放| 牛人盗摄一区二区三区视频| 久久精品视频免费播放| 欧美无砖砖区免费| 亚洲三级视频在线观看| 在线免费不卡视频| 久久精品99无色码中文字幕| 亚洲图片欧洲图片av| 免费在线亚洲| 欧美大片在线观看一区| 一区二区三区在线免费观看| 欧美一级大片在线观看| 性亚洲最疯狂xxxx高清| 国产精品jvid在线观看蜜臀| 亚洲精品社区| 一区二区三区视频在线看| 欧美精品成人一区二区在线观看| 欧美韩国一区| 亚洲日本中文字幕免费在线不卡| 久久久蜜臀国产一区二区| 免费成人毛片| 亚洲电影在线播放| 免费黄网站欧美| 亚洲三级视频| 亚洲综合电影| 国产一区二区三区在线观看免费| 亚洲免费在线观看| 欧美在线播放视频| 韩国三级电影一区二区| 久久午夜av| 最新国产成人在线观看| 亚洲视频在线观看视频| 国产精品高清在线| 欧美一级艳片视频免费观看| 久久久噜噜噜久久久| 亚洲电影免费在线| 欧美大片一区| 亚洲午夜91| 另类av一区二区| 99国产成+人+综合+亚洲欧美| 国产精品成人aaaaa网站| 欧美一区成人| 亚洲国产成人久久综合一区| 在线一区二区视频| 国产欧美日韩亚洲精品| 久久青草久久| 日韩视频中文| 久久全国免费视频| 日韩亚洲综合在线| 国产日韩精品视频一区| 嫩草国产精品入口| 亚洲一区日本| 欧美激情中文不卡| 亚洲欧美日本伦理| 亚洲成人在线网站| 欧美午夜宅男影院| 美脚丝袜一区二区三区在线观看 | 国产精品99久久久久久久vr| 国产精品视屏| 欧美高清视频在线播放| 性亚洲最疯狂xxxx高清| 亚洲激情成人| 久久综合色88| 性久久久久久久久久久久| 亚洲免费成人av| 黄色在线一区| 国产精品天天看| 欧美精品在线免费| 欧美二区在线看| 欧美在线一级视频| 一区二区三区四区五区精品视频 | 亚洲黄色高清| 国产精品午夜视频| 欧美精品1区2区| 老司机成人在线视频| 午夜欧美大片免费观看| 日韩五码在线| 欧美性大战久久久久久久| 久久国产精品色婷婷| 99热精品在线观看| 亚洲国产午夜| 亚洲电影有码| 男男成人高潮片免费网站| 久久黄色小说| 久久国产精品一区二区|