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

隨筆 - 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>
            国产一在线精品一区在线观看| 亚洲另类在线视频| 米奇777超碰欧美日韩亚洲| 亚洲国产91| 国产欧美一区二区三区视频| 欧美三级日韩三级国产三级| 欧美人与性动交cc0o| 欧美日韩国产不卡在线看| 久久亚裔精品欧美| 久久久久网址| 久久综合激情| 久久久久九九九九| 久久视频在线看| 欧美大片网址| 欧美精品日韩精品| 欧美一区二区在线免费观看| 久久精品国产欧美激情| 午夜在线观看免费一区| 久久噜噜亚洲综合| 欧美激情 亚洲a∨综合| 免播放器亚洲一区| 国产精品分类| 国产日产欧美一区| 欧美色精品在线视频| 国内精品久久久久久久影视蜜臀 | 久久综合五月| 美女精品国产| 欧美片在线播放| 国产精品a久久久久久| 国产精品一区毛片| 黄色日韩网站| 亚洲小少妇裸体bbw| 久久综合久久美利坚合众国| 欧美成人免费一级人片100| 亚洲视频在线观看视频| 久久久激情视频| 欧美女人交a| 黑人操亚洲美女惩罚| 在线观看不卡| 国内精品视频一区| 欧美一区二区三区四区在线观看| 狼人社综合社区| 亚洲一区制服诱惑| 麻豆视频一区二区| 国产麻豆日韩欧美久久| 日韩一级成人av| 欧美在线观看网址综合| 亚洲黄色片网站| 久久综合九色综合久99| 亚洲视频一起| 国产精品久久久久9999| 在线看日韩欧美| 欧美亚洲一区二区三区| 一本色道久久综合亚洲精品不卡 | 久久亚洲二区| 国产精品高潮呻吟久久av无限| 国产亚洲欧美日韩美女| 欧美在线观看视频| 99在线精品视频在线观看| 亚洲综合色在线| 国产欧美日韩精品专区| 亚洲狼人精品一区二区三区| 欧美国产亚洲精品久久久8v| 亚洲欧美国产精品专区久久| 欧美精品免费看| 亚洲小说欧美另类婷婷| 亚洲国产欧美另类丝袜| 日韩小视频在线观看| 欧美日韩午夜在线| 日韩五码在线| 99这里只有精品| 欧美精品福利视频| 日韩视频免费在线| 欧美成人在线网站| 亚洲免费在线视频一区 二区| 欧美日本亚洲| 在线视频精品一区| 欧美韩日一区| 亚洲高清影视| 亚洲综合另类| 欧美大片一区二区三区| 欧美a级片网| 99re亚洲国产精品| 亚洲天堂av高清| 欧美三级黄美女| 亚洲欧美三级伦理| 午夜久久福利| 国内精品美女在线观看| 亚洲国产欧美一区二区三区久久 | 性久久久久久久久久久久| 日韩视频在线观看免费| 欧美激情中文字幕乱码免费| 亚洲日韩欧美视频| 亚洲大胆女人| 欧美日韩午夜剧场| 久久av在线看| 欧美大片第1页| 亚洲综合二区| 久久精品中文字幕一区二区三区 | 一本久久a久久免费精品不卡 | 午夜视频在线观看一区| 国产一区二区三区日韩欧美| 亚洲精选视频免费看| 国产精品乱子乱xxxx| 欧美大片va欧美在线播放| 欧美日韩国产在线播放| 欧美主播一区二区三区| 欧美国产一区二区| 欧美一区二区私人影院日本 | 欧美制服丝袜第一页| 久久综合色婷婷| 一区二区三区久久| 尤物精品在线| 另类春色校园亚洲| 亚洲一区二区三区四区中文 | 欧美日韩1234| 欧美国产第一页| 亚洲人体一区| 国产日韩精品在线播放| 亚洲欧美经典视频| 久久久久久久一区| 曰韩精品一区二区| 日韩亚洲欧美高清| 日韩一二三区视频| 在线不卡中文字幕| 一区二区三区欧美日韩| 久久免费精品日本久久中文字幕| 91久久久久久国产精品| 精品不卡一区| 91久久精品国产91久久性色tv| 激情一区二区三区| 亚洲国产精品黑人久久久| 一区二区在线观看视频| 亚洲国产精品久久精品怡红院| 在线观看91精品国产麻豆| 一区二区激情视频| 亚洲欧美日韩在线| 麻豆国产精品一区二区三区| 亚洲美女91| 欧美视频日韩视频| 午夜久久久久久| 日韩亚洲在线观看| 玉米视频成人免费看| 亚洲激情一区二区三区| 国内揄拍国内精品少妇国语| 国产麻豆一精品一av一免费| 欧美日韩免费看| 欧美激情综合网| 国产精品自在在线| 99精品国产一区二区青青牛奶| 国产主播一区二区| 午夜电影亚洲| 久久九九99视频| 国户精品久久久久久久久久久不卡 | 亚洲精品女人| 久久资源在线| 亚洲第一中文字幕在线观看| 国产日韩专区在线| 亚洲在线观看| 久久久久在线| 狠狠色狠狠色综合人人| 亚洲午夜在线观看| 久久久精品2019中文字幕神马| 国产啪精品视频| 久久天天狠狠| 亚洲国产专区| 在线一区亚洲| 国产日本欧美一区二区三区| 亚洲综合社区| 国产精品美女视频网站| 国产精品第一区| 国产精品美女| 亚洲欧美日韩综合国产aⅴ| 久久久噜噜噜久久中文字幕色伊伊| 国产精品午夜视频| 麻豆国产精品va在线观看不卡| 欧美国产亚洲另类动漫| 中国女人久久久| 一区二区三区中文在线观看 | 性欧美video另类hd性玩具| 久久激情五月丁香伊人| 一区二区三区亚洲| 欧美午夜精品理论片a级按摩| 亚洲一区二区三区视频| 久久九九久精品国产免费直播 | 六月婷婷久久| 一本久久知道综合久久| 国内精品国语自产拍在线观看| 欧美国产日韩一区二区| 99国产精品久久久久老师| 久久免费视频在线观看| 亚洲蜜桃精久久久久久久| 国产伦理一区| 欧美日韩精品欧美日韩精品 | 国产一区二区三区电影在线观看| 久久日韩精品| 欧美在线观看一二区| 亚洲国产高潮在线观看| 中日韩美女免费视频网址在线观看 | 欧美黄色aaaa|