嵌入式数据库系统Berkeley DB

来源:互联网 发布:hadoop mac 还是linux 编辑:程序博客网 时间:2024/05/02 01:08

        mysql基于Berkeley DB开发的,Berkeley DB是历史悠久的嵌入式数据库系统,主要应用在UNIX/LINUX操作系统上,其设计思想是简单、小巧、可靠、高性能。

       DB的设计思想

         1,DB 有自己的api函数,来处理对数据的操作,这样节省了将SQL语句翻译的过程。

         2,DB是非网络数据库,而且DB和运行程序在同一个内存地址空间里面,这样节约了函数调用的时间,也避免了进程外通信之类的问题。

         3,DB的每个基础功能模块都是独立设计的,这样这些程序不仅仅适用于DB(GUN)。

         4,  不支持ISAM表。

         5, 没有自定义函数(UDF)。

         6, 没有内部RAID支持。 (由于大多数当前操作系统均支持大文件,通常情况下不需要它)。

         7,不能将其设置为“主”或“从”(无复制)。

         8,在内存较低的系统上,可能无法使用很大的结果集。

       DB的数据结构

         1,数据库句柄结构DB:包含数据库的属性参数,和数据操作的函数。

         2,数据库结构记录DBT:关键字和数据构成。关键字包含两个重要结构void * data和u_int32_t_size,分别对应数据本身和数据的长度。

         3,数据库游标结构DBC:游标(cursor)是数据库应用中常见概念,其本质上就是一个关于特定记录的遍历器。DB支持多重遍历。

        4,数据库环境句柄结构DB_ENV:环境在DB中属于高级特性,本质上看,环境是多个数据库的包装器。当一个或多个数据库在环境中打开后,环境可以为这些数据库提供多种子系统服务,例如多线/进程处理支持、事务处理支持、高性能支持、日志恢复支持等。

 

       DB数据访问算法
       B+树算法:B+树是一个平衡树,关键字有序存储,并且其结构能随数据的插入和删除进行动态调整。为了代码的简单,DB没有实现对关键字的前缀码压缩。B+树支持对数据查询、插入、删除的常数级速度。关键字可以为任意的数据结构。

       HASH算法:DB中实际使用的是扩展线性HASH算法(extended linear hashing),可以根据HASH表的增长进行适当的调整。关键字可以为任意的数据结构。

      Recno算法: 要求每一个记录都有一个逻辑纪录号,逻辑纪录号由算法本身生成。实际上,这和关系型数据库中逻辑主键通常定义为int AUTO型是同一个概念。Recho建立在B+树算法之上,提供了一个存储有序数据的接口。记录的长度可以为定长或不定长。

      Queue算法:和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游标使用范例

游标是依赖于数据库句柄的,应用程序代码框架如下:

/* 定义一个游标变量 */DBC * cur;/* 首先打开数据库,再打开游标 */dbp->open(dbp, ……);dbp->cursor(dbp, NULL, &cur, 0);/* do something with cursor *//* 首先关闭,在关闭数据库 */cur->c_close(cur);dbp->close(dbp, 0);

在游标打开后,可以以多种方式遍历特定记录。

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。例如:

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数据库的包装器,提供多种高级功能。应用程序代码框架如下:

/* 定义一个环境变量,并创建 */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,解压到工作目录,进入该目录,依次执行下列三条命令即可。

../dist/configuremakemake 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内部对数据的操作,提高数据的访问效率。

 

参考文章地址:http://www-128.ibm.com/developerworks/cn/linux/l-embdb/

原创粉丝点击