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

eryar

PipeCAD - Plant Piping Design Software.
RvmTranslator - Translate AVEVA RVM to OBJ, glTF, etc.
posts - 603, comments - 590, trackbacks - 0, articles - 0

【轉】嵌入式數據庫系統Berkeley DB

Posted on 2018-11-22 09:57 eryar 閱讀(1709) 評論(0)  編輯 收藏 引用 所屬分類: 5.Database

原文地址:https://www.ibm.com/developerworks/cn/linux/l-embdb/index.html

前言

UNIX/LINUX平臺下的數據庫種類非常多,參考資料1中列舉了其中的大部分。通常,我們在設計UNIX/LINUX平臺下的應用軟件時,如果數據種類繁多,數據與數據之間關系比較復雜,就會選用一些大型的企業級數據庫系統,如DB2,ORACLE、SYBASE等,如果軟件規模不大,就傾向選用如MYSQL、POSTGRESQL等中小型數據庫。例如使用PHP/PERL + MYSQL/POSTGRESQL設計網站基本上是一個很常規的做法。但是,當應用軟件管理的數據類型較少(特別注意:這并不是說需要管理的數據量小),數據管理本身不復雜,且對數據操作要求高效率,則由大名鼎鼎的Berkeley(美國加州大學伯克利分校)開發的 Berkeley DB可能是一個很明智的選擇。

DB綜述

DB最初開發的目的是以新的HASH訪問算法來代替舊的hsearch函數和大量的dbm實現(如AT&T的dbm,Berkeley的ndbm,GNU項目的gdbm),DB的第一個發行版在1991年出現,當時還包含了B+樹數據訪問算法。在1992年,BSD UNIX第4.4發行版中包含了DB1.85版。基本上認為這是DB的第一個正式版。在1996年中期,Sleepycat軟件公司成立,提供對DB的商業支持。在這以后,DB得到了廣泛的應用,當前最新版本是4.3.27。

DB支持幾乎所有的現代操作系統,如LINUX、UNIX、WINDOWS等,也提供了豐富的應用程序接口,支持C、C++、JAVA、PERL、TCL、PYTHON、PHP等。DB的應用十分廣泛,在很多知名的軟件中都能看到其身影。例如參考資料2中作者談到利用DB在LINUX下實現內核級文件系統;參考資料3中通過實際測試數據說明DB提高了OPENLDAP的效率。LINUX下的軟件包管理器RPM也使用DB管理軟件包相關數據,可以使用命令file查看RPM數據目錄/var/lib/rpm下的文件,則有形式如下的輸出:

Dirnames: Berkeley DB (Btree, version 9, native byte-order)
Filemd5s: Berkeley DB (Hash, version 8, native byte-order)

值得注意的是DB是嵌入式數據庫系統,而不是常見的關系/對象型數據庫,對SQL語言不支持,也不提供數據庫常見的高級功能,如存儲過程,觸發器等。

DB的設計思想

DB的設計思想是簡單、小巧、可靠、高性能。如果說一些主流數據庫系統是大而全的話,那么DB就可稱為小而精。DB提供了一系列應用程序接口(API),調用本身很簡單,應用程序和DB所提供的庫在一起編譯成為可執行程序。這種方式從兩方面極大提高了DB的效率。第一:DB庫和應用程序運行在同一個地址空間,沒有客戶端程序和數據庫服務器之間昂貴的網絡通訊開銷,也沒有本地主機進程之間的通訊;第二:不需要對SQL代碼解碼,對數據的訪問直截了當。

DB對需要管理的數據看法很簡單,DB數據庫包含若干條記錄,每一個記錄由關鍵字和數據(KEY/VALUE)構成。數據可以是簡單的數據類型,也可以是復雜的數據類型,例如C語言中結構。DB對數據類型不做任何解釋, 完全由程序員自行處理,典型的C語言指針的"自由"風格。如果把記錄看成一個有n個字段的表,那么第1個字段為表的主鍵,第2--n個字段對應了其它數據。DB應用程序通常使用多個DB數據庫,從某種意義上看,也就是關系數據庫中的多個表。DB庫非常緊湊,不超過500K,但可以管理大至256T的數據量。

DB的設計充分體現了UNIX的基于工具的哲學,即若干簡單工具的組合可以實現強大的功能。DB的每一個基礎功能模塊都被設計為獨立的,也即意味著其使用領域并不局限于DB本身。例如加鎖子系統可以用于非DB應用程序的通用操作,內存共享緩沖池子系統可以用于在內存中基于頁面的文件緩沖。

DB核心數據結構

數據庫句柄結構DB:包含了若干描述數據庫屬性的參數,如數據庫訪問方法類型、邏輯頁面大小、數據庫名稱等;同時,DB結構中包含了大量的數據庫處理函數指針,大多數形式為 (*dosomething)(DB *, arg1, arg2, …)。其中最重要的有open,close,put,get等函數。

數據庫記錄結構DBT:DB中的記錄由關鍵字和數據構成,關鍵字和數據都用結構DBT表示。實際上完全可以把關鍵字看成特殊的數據。結構中最重要的兩個字段是 void * data和u_int32_t size,分別對應數據本身和數據的長度。

數據庫游標結構DBC:游標(cursor)是數據庫應用中常見概念,其本質上就是一個關于特定記錄的遍歷器。注意到DB支持多重記錄(duplicate records),即多條記錄有相同關鍵字,在對多重記錄的處理中,使用游標是最容易的方式。

數據庫環境句柄結構DB_ENV:環境在DB中屬于高級特性,本質上看,環境是多個數據庫的包裝器。當一個或多個數據庫在環境中打開后,環境可以為這些數據庫提供多種子系統服務,例如多線/進程處理支持、事務處理支持、高性能支持、日志恢復支持等。

DB中核心數據結構在使用前都要初始化,隨后可以調用結構中的函數(指針)完成各種操作,最后必須關閉數據結構。從設計思想的層面上看,這種設計方法是利用面向過程語言實現面對對象編程的一個典范。

DB數據訪問算法

在數據庫領域中,數據訪問算法對應了數據在硬盤上的存儲格式和操作方法。在編寫應用程序時,選擇合適的算法可能會在運算速度上提高1個甚至多個數量級。大多數數據庫都選用B+樹算法,DB也不例外,同時還支持HASH算法、Recno算法和Queue算法。接下來,我們將討論這些算法的特點以及如何根據需要存儲數據的特點進行選擇。

B+樹算法:B+樹是一個平衡樹,關鍵字有序存儲,并且其結構能隨數據的插入和刪除進行動態調整。為了代碼的簡單,DB沒有實現對關鍵字的前綴碼壓縮。B+樹支持對數據查詢、插入、刪除的常數級速度。關鍵字可以為任意的數據結構。

HASH算法:DB中實際使用的是擴展線性HASH算法(extended linear hashing),可以根據HASH表的增長進行適當的調整。關鍵字可以為任意的數據結構。

Recno算法: 要求每一個記錄都有一個邏輯紀錄號,邏輯紀錄號由算法本身生成。實際上,這和關系型數據庫中邏輯主鍵通常定義為int AUTO型是同一個概念。Recho建立在B+樹算法之上,提供了一個存儲有序數據的接口。記錄的長度可以為定長或不定長。

Queue算法:和Recno方式接近, 只不過記錄的長度為定長。數據以定長記錄方式存儲在隊列中,插入操作把記錄插入到隊列的尾部,相比之下插入速度是最快的。

對算法的選擇首先要看關鍵字的類型,如果為復雜類型,則只能選擇B+樹或HASH算法,如果關鍵字為邏輯記錄號,則應該選擇Recno或Queue算法。當工作集關鍵字有序時,B+樹算法比較合適;如果工作集比較大且基本上關鍵字為隨機分布時,選擇HASH算法。Queue算法只能存儲定長的記錄,在高的并發處理情況下,Queue算法效率較高;如果是其它情況,則選擇Recno算法,Recno算法把數據存儲為平面文件格式。

DB常用函數使用范例

#include <db.h> 
#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); 
}

DB游標使用范例

游標是依賴于數據庫句柄的,應用程序代碼框架如下:

1
2
3
4
5
6
7
8
9
10
/* 定義一個游標變量 */
DBC * cur;
/* 首先打開數據庫,再打開游標 */
dbp->open(dbp, ……);
dbp->cursor(dbp, NULL, &cur, 0);
 
/* do something with cursor */
/* 首先關閉,在關閉數據庫 */
cur->c_close(cur);
dbp->close(dbp, 0);

在游標打開后,可以以多種方式遍歷特定記錄。

1
2
3
4
5
6
7
    Memset(&key, 0, sizeof(DBT));
Memset(&data, 0, sizeof(DBT));
/* 因為KEY和DATA為空,則游標遍歷整個數據庫記錄 */
While((ret = cur->c_get(cur, &key, &data, DB_NEXT)) == 0)
{
    /* do something with key and data */
}

當想查詢特定關鍵字對應的記錄,則應對關鍵字賦值,并把cur->c_get()函數中標志位設置為DB_SET。例如:

1
2
3
4
5
6
    key.data = "xxxxx";
key.size =  XXX;
While((ret = cur->c_get(cur, &key, &data, DB_SET)) == 0)
{
    /* do something with key and data */
}

游標的作用還有很多,如查詢多重記錄,插入/修改/刪除記錄等。

DB環境使用范例

本文前面已說明環境是DB數據庫的包裝器,提供多種高級功能。應用程序代碼框架如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/* 定義一個環境變量,并創建 */
  DB_ENV *dbenv;
  db_env_create(&dbenv, 0);
   
/* 在環境打開之前,可調用形式為dbenv->set_XXX()的若干函數設置環境 */
  /* 通知DB使用Rijndael加密算法(參考資料>)對數據進行處理 */
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);

DB軟件的安裝和編譯

從DB的官方站點http://www.sleepycat.com/下載最新的軟件包db-4.3.27.tar.gz,解壓到工作目錄,進入該目錄,依次執行下列三條命令即可。

1
2
3
../dist/configure
make
make install

執行make uninstall,則可卸載已安裝的DB軟件。

DB缺省把庫和頭文件安裝在目錄/usr/local/BerkeleyDB.4.3/下,使用gcc test.c -ggdb -I/usr/local/BerkeleyDB.4.3/include/ -L/usr/local/BerkeleyDB.4.3/lib/ -ldb -lpthread就可正確編譯程序。如果讀者的測試主機操作系統為RED HAT9,則安裝的DB版本可能是4.0。特別要注意到這兩個版本的庫是不兼容的。例如打開數據庫函數DB->open(),在4.0版本中入參為6個,而在4.3版中則為7個(可自行比較兩個庫的頭文件db.h中DB->open函數的定義)。因為在DB相關的應用程序中,open函數基本上都是要執行的,所以如果函數和版本不匹配,編譯肯定會出錯。當然,編譯完成后,可以使用命令ldd查看庫的依賴關系。

總結

DB是一個具有工業強度的嵌入式數據庫系統,數據處理的效率很高。DB功能的穩定性歷經時間的考驗,在大量應用程序中使用便是明證。可以想見,在同等代碼質量的條件下,軟件的BUG數和代碼的長度是成正比的,相對幾十兆、幾百兆大型數據庫軟件,DB的只有不到500K的大小!

從實現功能上看,DB是輕量級數據庫系統,或可稱為"極" 輕量級數據庫系統。但是,我認為不能因此而心存輕視之意,所謂"尺有所短,寸有所長",以絕對角度比較工具之間的好壞是沒有什么意義的,關鍵在于對工具的選擇和運用(似乎可以參考一下極限編程的思想)。也許,正確的"表達范式"應該是:在當前應用背景下,選擇這種工具是最合適的。

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            国产精品美女999| 久久成人一区| 一本色道综合亚洲| 亚洲二区视频在线| 国产一区二区精品丝袜| 欧美韩日一区二区| 欧美成人中文| 亚洲国产精品尤物yw在线观看| 亚洲视频观看| 黄色精品网站| 欧美制服丝袜| 在线一区欧美| 午夜精品久久久久久久久久久| 一本色道久久88综合亚洲精品ⅰ | 亚洲电影在线| 亚洲国产成人久久综合一区| 免费91麻豆精品国产自产在线观看| 久久高清福利视频| 久久亚洲一区二区| 亚洲国产欧美另类丝袜| 亚洲精品欧美专区| 亚洲欧美国产高清| 久久久久国产精品人| 欧美国产极速在线| 国产精品国产| 亚洲毛片一区二区| 欧美在线高清视频| 亚洲欧洲日本专区| 久久gogo国模啪啪人体图| 欧美美女视频| 亚洲第一黄色| 久久精品国产91精品亚洲| 欧美怡红院视频| 亚洲国产精品综合| 久久久久九九视频| 国产日韩欧美在线观看| 中文久久乱码一区二区| 亚洲高清自拍| 美女精品网站| 亚洲精品小视频在线观看| 亚洲图片欧美午夜| 日韩一本二本av| 欧美日韩国产综合一区二区| 亚洲成在人线av| 欧美高清在线视频| 欧美区高清在线| 国产精品一二| 一本色道久久88综合日韩精品| 国产精品一区二区视频| 欧美中文字幕视频| 欧美日韩午夜视频在线观看| 91久久亚洲| 99国产精品国产精品久久| 国产精品资源| 久久午夜羞羞影院免费观看| 激情综合色综合久久| 日韩午夜在线观看视频| 亚洲欧洲精品一区二区精品久久久| 久久久久一区| 亚洲一卡久久| 久久久久一区二区三区| 亚洲最快最全在线视频| 亚洲视频一二| 最新国产の精品合集bt伙计| 亚洲一区尤物| 美女黄毛**国产精品啪啪| 美日韩精品免费观看视频| 亚洲欧美另类综合偷拍| 免费观看久久久4p| 久久成人综合视频| 欧美日韩一区在线| 亚洲福利专区| 国产精自产拍久久久久久蜜| 亚洲在线免费| 欧美成人亚洲成人| 久久久国产一区二区| 欧美午夜剧场| 亚洲精品日本| 一区二区三区福利| 欧美激情在线免费观看| 欧美一区二区日韩| 欧美日产国产成人免费图片| 午夜精品av| 欧美日产国产成人免费图片| 欧美成人午夜激情视频| 国产亚洲福利一区| 性久久久久久久久| 香蕉免费一区二区三区在线观看| 国产精品免费观看视频| 亚洲一级二级| 久久成人免费| 亚洲无限av看| 男人插女人欧美| 伊人精品视频| 欧美1区免费| 日韩午夜黄色| 久久久国产视频91| 亚洲看片一区| 国产日本欧美在线观看| 久久久噜噜噜久噜久久 | 亚洲国产精品久久久久秋霞蜜臀 | 国语精品一区| 欧美日韩亚洲一区三区| 欧美一区二区私人影院日本| 嫩草影视亚洲| 午夜精品影院| 在线亚洲一区二区| 久久久免费精品视频| 亚洲精品视频免费观看| 亚洲欧美日韩一区| 亚洲国产成人精品视频| 国产精品一区二区在线观看网站| 久久欧美中文字幕| 亚洲免费一级电影| 99在线精品观看| 亚洲日本欧美在线| 欧美va天堂| 你懂的网址国产 欧美| 亚洲欧美国产77777| 韩国精品在线观看| 国产伊人精品| 韩国v欧美v日本v亚洲v| 宅男噜噜噜66国产日韩在线观看| 国内精品一区二区| 亚洲高清在线精品| 影音先锋久久资源网| 韩国在线一区| 亚洲精品国产拍免费91在线| 一本一本久久| 亚洲先锋成人| 狠狠久久婷婷| 日韩午夜av在线| 亚洲激情视频| 日韩视频一区二区在线观看 | 久久九九全国免费精品观看| 久久精品国产99精品国产亚洲性色| 亚洲精选大片| 亚洲无线视频| 久久黄金**| 牛牛国产精品| 国产精品国产一区二区| 国产自产在线视频一区| 99精品久久久| 欧美3dxxxxhd| 午夜久久福利| 欧美视频成人| 一区二区在线免费观看| 中文欧美字幕免费| 久久中文字幕一区| 欧美激情中文不卡| 欧美一区二区三区久久精品茉莉花| 免费在线欧美视频| 国产精品久久毛片a| 亚洲视频免费在线| 欧美成人精品在线视频| 亚洲深夜福利在线| 欧美日韩免费高清一区色橹橹| 黄色综合网站| 久久色中文字幕| 亚洲欧美在线aaa| 老司机精品视频网站| 国产日韩欧美在线观看| 免费国产一区二区| 国产精品视频免费一区| 亚洲影院色无极综合| 在线一区欧美| 国产精品一区二区三区成人| 亚洲在线免费| 亚洲女人天堂成人av在线| 国产精品视频一二三| 欧美一区二区视频网站| 亚洲午夜一区二区| 国产欧美日韩在线视频| 浪潮色综合久久天堂| 欧美激情精品久久久六区热门| 亚洲日本一区二区| 欧美亚洲一区二区三区| 一区二区在线观看视频在线观看| 欧美电影在线免费观看网站| 欧美日韩日日骚| 久久久水蜜桃| 欧美色综合天天久久综合精品| 久久成人一区二区| 国产精品va在线播放我和闺蜜| 久久精品毛片| 国产精品久久久久免费a∨大胸 | 欧美高清视频在线播放| 亚洲午夜国产一区99re久久| 久久精品亚洲| 欧美一区二区在线视频| 欧美香蕉大胸在线视频观看| 久久久999精品免费| 亚洲电影下载| 亚洲综合日韩在线| 中日韩午夜理伦电影免费| 欧美成人综合网站| 欧美激情第三页| 亚洲欧洲日产国产综合网| 另类欧美日韩国产在线| 新狼窝色av性久久久久久|