Berkeley DB使用簡介

Berkeley DB使用簡介 1來源: 作者: 時間:2007-12-02 Tag: 點擊: 587 1        簡介

BDB的全稱Berkeley DB,是一套開放源碼的嵌入式數據庫的程序庫。它爲應用程序提供可伸縮的、高性能的、有事務保護功能的數據管理服務。Berkeley DB爲數據的存取和管理提供了一組簡潔的函數調用API接口。

BDB爲多種編程語言提供了API接口,其中包括C、C++、Java、Perl、Tcl、Python和PHP,所有的數據庫操作都在程序庫內部發生。多個進程,或者同一進程的多個線程可同時使用數據庫,有如各自單獨使用,底層的服務如加鎖、事務日誌、共享緩衝區管理、內存管理等等都由程序庫透明地執行。

BDB物理結構:

2        存儲邏輯介紹

BDB所管理數據的邏輯組織單位是若干個獨立或有一定關係的數據庫(database),每個數據庫由若干記錄組成,這些記錄全都被表示成(key,value)的形式。

如果把一組相關的(key,value)對也看作一個表的話,那麼每一個數據庫只允許存放一個table,這一點不同於一般的關係數據庫。實際上,在Berkeley DB中所提到的“數據庫”,相當於一般關係數據庫系統中的表;而“key/data”對相當於關係數據庫系統中的行(rows);Berkeley DB不提供關係數據庫中列直接訪問的功能,而是在“key/data”對中的data項中通過實際應用來封裝字段(列)。

在物理組織上,每一個數據庫在創建的時候可以由應用程序根據其數據特點來選擇一種合適的存儲結構。可供選擇的四種文件存儲結構分別是:哈希、B樹、定長記錄(隊列)和變長記錄(基於記錄號的簡單存儲方式)。

其中定長記錄和變長記錄存儲方法必須使用邏輯記錄號(logical record numbers,本質上就是一個整數)做爲key。

哈希和B樹存儲方法對key沒有特別的要求。當數據量非常多時(內存不能放下所有數據時),建議使用哈希,因爲哈希比B樹的索引信息小,會少一些I/O操作。
3        系統結構介紹:

BDB由五個主要的子系統構成.包括: 存取管理子系統、內存池管理子系統、事務子系統、鎖子系統以及日誌子系統。     
3.1      數據存取子系統

    數據存取(Access Methods)子系統爲創建和訪問數據庫文件提供了多種支持。Berkeley DB提供了以下四種文件存儲方法:

哈希文件、B樹、定長記錄(隊列)和變長記錄(基於記錄號的簡單存儲方式),應用程序可以從中選擇最適合的文件組織結構。

創建表時可以使用任意一種結構,並且可以在同一個應用程序中對不同存儲類型的文件進行混合操作。
3.2      內存池管理子系統

    內存池(Memory pool)子系統對Berkeley DB所使用的共享緩衝區進行有效的管理。它允許同時訪問數據庫的多個進程或者進程的多個線程共享一個高速緩存,負責將修改後的頁寫回文件和爲新調入的頁分配內存空間。

    它也可以獨立於Berkeley DB系統之外,單獨被應用程序使用,爲其自己的文件和頁分配內存空間。

內存池管理子系統適用於需要靈活的、面向頁的、緩衝的共享文件訪問的應用。

內存數據和硬盤文件的同步有兩種方式:

1.         需要程序顯式條用同步函數才能完成,當數據量比較大時同步比較慢,會造成大量的I/O操作,而且由於內部鎖的原因,會對查詢造成影響。

2.         在BDB打開時會設置一個cache的大小,也就是BDB使用內存的大小。如果超過這個大小,BDB會自動同步數據到硬盤文件。
3.3      事務子系統

 

本文來自: (www.91linux.com) 詳細出處參考:http://www.91linux.com/html/article/database/20071202/8699.html

 

 

 事務(Transaction)子系統爲Berkeley DB提供事務管理功能。它允許把一組對數據庫的修改看作一個原子單位,這組操作要麼全做,要麼全不做。在默認的情況下,系統將提供嚴格的ACID事務屬性,但是應用程序可以選擇不使用系統所作的隔離保證。該子系統使用兩段鎖技術和先寫日誌策略來保證數據庫數據的正確性和一致性。

它也可以被應用程序單獨使用來對其自身的數據更新進行事務保護。事務子系統適用於需要事務保證數據的修改的應用。

在本次項目裏,並沒有用到事務,所以對此研究也不夠深入。
3.4      鎖子系統

    鎖(Locking)子系統爲BDB提供鎖機制,爲系統提供多用戶讀取和單用戶修改同一對象的共享控制。

數據存取子系統可利用該子系統獲得對頁或記錄的讀寫權限;事務子系統利用鎖機制來實現多個事務的併發控制。  

該子系統也可被應用程序單獨採用。鎖子系統適用於一個靈活的、快速的、可設置的鎖管理器。

目前的使用上來看,當使用BDB的進程異常終止時,所佔用的鎖並不能釋放,需要刪除BDB環境文件才能釋放所有鎖。這個問題後期再詳細研究一下。
3.5      日誌子系統

日誌(Logging)子系統採用的是先寫日誌的策略,用於支持事務子系統進行數據恢復,保證數據一致性。
4        編譯、安裝

可以在http://www.oracle.com/technology/products/berkeley-db/index.html 現在最新的安裝包和文檔。

       將安裝包結壓後,進入build_unix目錄

    ../dist/configure

    Make

    Make install

    就可以完成編譯,安裝

       安裝的默認目錄是/usr/local/BerkeleyDB.4.5/,如果要安裝到其他目錄,在configure是指定--prefix=NEW_DIR即可。如果要使用BDB的c++,在configure指定--enable-cxx即可。


本文來自: (www.91linux.com) 詳細出處參考:http://www.91linux.com/html/article/database/20071202/8699_2.html

 

 

 

5        C++API介紹

經常用的類有5個

1.         DbEnv:環境類,主要用於設置BDB是否需要日誌、是否需要鎖等信息;提供打開、關閉等操作

2.         Db:DB類,用戶操作數據,提供打開、關閉、查找、刪除、同步等操作

3.         Dbt:數據類,向Db中存入、取出數據都需要使用這個類。

4.         DbException及其子類:異常類

5.         Dbc:遊標類,當對數據庫中多組數據進行操作時使用

#include <db_cxx.h>

#include <string>

#include <iostream>

using namespace std;

DbEnv *g_env = NULL;

Db *g_db = NULL;

void closeEnv()

{

    try

    {

        if(g_db)

        {

            g_db->close(0);

            delete g_db;

            g_db = NULL;

        }

        if(g_env)

        {

            g_env->close(0);

            delete g_env;

            g_env = NULL;

        }

    }

    catch(...)

    {

    }

}

int main()

{

    //環境目錄,日誌文件將創建在這個目錄下

    string strEnvHome = "./db/";

    //創建DB|初始化日誌

    unsigned int nEnvFlags = DB_CREATE | DB_INIT_LOG | DB_INIT_MPOOL;  

  

    //db文件名

    string strDbFileName = get_current_dir_name();

    strDbFileName += "/db/datafile";  

  

    try

    {

        g_env = new DbEnv(0);

        g_env->set_error_stream(&std::cerr);

        g_env->set_cachesize(0, 10 * 1024 * 1024, 1);

        //打開環境

        g_env->open(strEnvHome.c_str(), nEnvFlags, 0);

      

        g_db = new Db(g_env, 0);

        g_db->set_error_stream(&std::cerr);

        //用B樹的結構打開數據庫,如果不存在則創建

        g_db->open(NULL, strDbFileName.c_str(), NULL, DB_BTREE, DB_CREATE, 0);

    }

    catch(DbException& e)

    {

        cout<<"打開數據庫出錯:"<<e.what()<<endl;

        closeEnv();

        return -1;

    }

  

    Dbt key, data;

    char sKey[1024], sData[1024];


本文來自: (www.91linux.com) 詳細出處參考:http://www.91linux.com/html/article/database/20071202/8698.html

 

 

 

 //插入數據庫

   try

   {

     for(int i=0; i<100; i++)

     {      

         snprintf(sKey, sizeof(sKey), "key%d", i);

         snprintf(sData, sizeof(sData), "data%d", i);

       

         key.set_data(sKey);

         key.set_size( strlen(sKey) );

         data.set_data(sData);

         data.set_size( strlen(sData) );

       

         //put方法:當數據庫中有對應的key時,做updata操作;當沒有對應的key時,做insert操作

         if( g_db->put(NULL, &key, &data, 0) != 0)

         {

            //插入出錯

            cout<<"插入第"<<i<<"個數據時出錯"<<endl;

         }

     }

   }

   catch(DbException& e)

   {

      cout<<"寫入數據庫出錯:"<<e.what()<<endl;

      closeEnv();

      return -1;

   }

  

    //同步內存的數據到文件

    g_db->sync(0);

  

    //查找數據

    try

    {

        snprintf(sKey, sizeof(sKey), "key%d", 57);

        key.set_data(sKey);

        key.set_size( strlen(sKey) );

      

        if(g_db->get(NULL, &key, &data, 0) != 0)

        {

            //未查找到

            cout<<"未查找到,key:"<<sKey<<endl;

        }

        else

        {

            //查找到

            memcpy(sData, data.get_data(), data.get_size() );

            sData[data.get_size()] = '/0';

          

            cout<<"key:"<<sKey<<";data:"<<sData<<endl;

        }

    }

    catch(DbException& e)

    {

      cout<<"查找數據庫出錯:"<<e.what()<<endl;

      closeEnv();

      return -1;

    }

  

    //用遊標遍歷

    try

    {

        Dbc *cursorp;      

           

        if( g_db->cursor(NULL, &cursorp, 0) != 0)

        {

            cout<<"[get cursor 錯誤."<<endl;

        }

        else

        {

            while (cursorp->get(&key, &data, DB_NEXT) == 0)

            {

                memcpy(sKey, key.get_data(), key.get_size() );

                sKey[key.get_size()] = '/0';

                memcpy(sData, data.get_data(), data.get_size() );

                sData[data.get_size()] = '/0';

              

                cout<<"key:"<<sKey<<";data:"<<sData<<endl;

            }

        }

    }

    catch(DbException& e)

    {

      cout<<"用遊標遍歷出錯:"<<e.what()<<endl;

      closeEnv();

      return -1;

    }

  

  

    closeEnv();

}

 

本文來自: (www.91linux.com) 詳細出處參考:http://www.91linux.com/html/article/database/20071202/8698_2.html

發佈了12 篇原創文章 · 獲贊 4 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章