發新話題

BDB, 嵌入式數據庫Berkeley DB, 入門知識

BDB, 嵌入式數據庫Berkeley DB, 入門知識

在網上看到不少介紹Berkeley DB的文章,幾乎所有的中文文章都是介紹完入門就再也沒了。大都是個概括。最近做這個,所以想系統的由淺入深的介紹一下。不清楚的地方可以和我討論,或參照官方網站sleepycat上的文檔。我用的是最新版本 db-4.4.16.NC.tar.gz,這個包中含有詳細的英文文檔。

為什麼要使用Berkeley DB,它適合什麼場合應用?
Berkeley DB並不適合所有的應用,因為簡單,專一所以高效。
嵌入式數據庫,的「嵌入」是指它內嵌在程序中,而不是說他只應用在嵌入式系統上。它的特點很適合應用於嵌入式系統上。當然在我們的pc機集群或大型服務器上,也可以靈活的配置,完成更艱巨的任務。

它適合於管理海量的,簡單的數據。Google用Berkeley DB HA (High Availability) 來管理他們的帳戶信息. Motorola在他的無線產品中用Berkeley DB跟蹤移動單元。hp,microsoft,Sun Microsystems...等也都是它的大客戶。它不能完全取代關係數據庫,但在某些方面,它卻有他們望塵莫及的高效性。

性能測試,在如下的配置上:
Linux – SuSE Linux 9.1 running on an AMD Athlon 64 processor 3200+ at 1GHz system with 1GB of RAM。
每秒鐘,單條記錄讀操作 1,002,200次。單條記錄寫操作 766,034次。 用bulk APIs能進行讀操作 13,501,800次。當然這些都是發生在內存中的操作,因為bdb使用了cache。 性能測試具體數據可以參考官方網站的Performance Metrics & Benchmarks: Berkeley DB。

Berkeley DB簡介
Berkeley DB可以說是一個專為程序員準備的數據庫。我的文章中只針對c程序員介紹的。它還支持C++、Java、Perl、Tcl、Python和PHP等。原理和接口都差不多。它的安裝很簡單。

cd build_unix
../dist/configure
make
make install

這幾步就ok了,其實也就是把頭文件和編譯好的db庫放到指特定位置。甚至可以不用make install,直接在編譯你的程序時用-I -L -ldb 指定頭文件和連接庫的位置。可以完全把它當作一個函數庫來用。由db庫透明的來完成對數據的管理。無論是系統中的多個進程,或者是相同進程中的多個線程,都可以在同一時間調用訪問數據庫的函數。而底層的數據加鎖、事務日誌和存儲管理等都在Berkeley DB函數庫中實現。他不像傳統的數據庫那樣有client和server,還專門跑幾個進程。所以應用程序不需要事先同數據庫服務建立起網絡連接,而是通過內嵌在程序中的Berkeley DB函數庫來完成對數據的保存、查詢、修改和刪除等操作。

Berkeley DB函數庫本身雖然只有300KB左右,但卻能夠用來管理多達256TB的數據,並且在許多方面的性能還能夠同商業級的數據庫系統相抗衡。就拿對數據的並發操作來說,Berkeley DB能夠很輕鬆地應付幾千個用戶同時訪問同一個數據庫的情況。因而,在資源受限的嵌入式系統上進行數據庫管理,Berkeley DB也是一個不錯的選擇。

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

基本概念
關鍵字/數據 是Berkeley DB用來進行數據庫管理的基礎。每個 Key/Data 對構成一條記錄。而整個數據庫實際上就是由許多這樣的結構單元所構成的。通過使用這種方式,開發人員在使用Berkeley DB提供的API來訪問數據庫時,只需提供關鍵字就能夠訪問到相應的數據。當然也可以也可以提供 Key 和部分Data來查詢符合條件的相近數據。

一個例子來完成入門
使用過rdb的人相信都能看的懂下面的例子。簡要的說一下下面持續完成的功能。作為一個簡單的例子environment部分可以不是必要的,我把它的用法也一起加了進來。創建一個environment指明要把數據庫文件創建到哪個目錄下面。創建數據庫,打開數據庫,寫一個記錄進去,然後讀出記錄,然後將寫入的記錄刪除,然後關閉environment和數據庫。會了這些基本操作,你就可以使用bdb完成簡單的應用了。
....................................................................

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//only this head should include for use bdb.
#include <db.h>  
#define DATABASE "yangjian.db"

int main()
{
    DB_ENV *myEnv;
    DB *dbp;
    DBT key, data;
    int ret,t_ret;
    u_int32_t env_flags;
    //........... Create an environment object and initialize it for error reporting
    ret = db_env_create(&myEnv, 0);
    if (ret != 0)
    {
          fprintf(stderr, "Error creating env handle: %s\n", db_strerror(ret));
          return -1;
    }
    //........If the environment does not exist create it. Initialize the in-memory cache.
    env_flags = DB_CREATE | DB_INIT_MPOOL;
    //........Open the environment.
    ret = myEnv->open(myEnv,"/home/yangbin1/yangjian/my/db/testevn",env_flags,0);
    if (ret != 0)
    {
          fprintf(stderr, "Environment open failed: %s", db_strerror(ret));
          return -1;
    }

    if ((ret = db_create(&dbp, myEnv, 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");
/*
    //......put data
    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");
    }
*/

    //........put data 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");

    //.......get data
    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");

    //......del data
    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");

    //.........close, only when the db successful closed,the data can real write to the disk.
    //if ((t_ret = dbp->close(dbp, 0)) != 0 && ret == 0)
    //ret = t_ret;
    //exit(ret);
    if (dbp != NULL)
    dbp->close(dbp, 0);
    //.........close evn
    //........When you are done with an environment, you must close it.
    //........Before you close an environment, make sure you close any opened databases
    if (myEnv != NULL)
    myEnv->close(myEnv, 0);

    return 0;
}

TOP

發新話題

本站所有圖文均屬網友發表,僅代表作者的觀點與本站無關,如有侵權請通知版主會盡快刪除。