一、Berkeley DB的介绍

(1)Berkeley DB是一个嵌入式数据库,它适合于管理海量的、简单的数据。如Google使用其来保存账户信息,Heritrix用其来保存froniter.

(2)key/value是Berkeley DB用来管理数据的基础,每个key/value对代表一条记录。

(3)Berkeley DB在底层实现采用B树,可以看成能够存储大量数据的HashMap。

(4)它是Oracle公司的一个产品,C++版本最新出现,之后JAVA等版本也陆续出现。它不支持SQL语句,应用程序通过API对数据库进行操作。

以下内容转载至百度文库

Berkeley DB是由美国Sleepycat Software公司开发的一套开放源码的嵌入式数据库的程序库(database library),它为应用程序提供可伸缩的、高性能的、有事务保护功能的数据管理服务。Berkeley DB为数据的存取和管理提供了一组简洁的函数调用API接口。

它是一个经典的C-library模式的toolkit,为程序员提供广泛丰富的函数集,是为应用程序开发者提供工业级强度的数据库服务而设计的。其主要特点如下:

    嵌入式(Embedded):它直接链接到应用程序中,与应用程序运行于同样的地址空间中,因此,无论是在网络上不同计算机之间还是在同一台计算机的不同进程之间,数据库操作并不要求进程间通讯。

    Berkeley DB为多种编程语言提供了API接口,其中包括C、C++、Java、Perl、Tcl、Python和PHP,所有的数据库操作都在程序库内部发生。多个进程,或者同一进程的多个线程可同时使用数据库,有如各自单独使用,底层的服务如加锁、事务日志、共享缓冲区管理、内存管理等等都由程序库透明地执行。

    轻便灵活(Portable):它可以运行于几乎所有的UNIX和Linux系统及其变种系统、Windows操作系统以及多种嵌入式实时操作系统之下。它在32位和64位系统上均可运行,已经被好多高端的因特网服务器、台式机、掌上电脑、机顶盒、网络交换机以及其他一些应用领域所采用。一旦Berkeley DB被链接到应用程序中,终端用户一般根本感觉不到有一个数据库系统存在。

    可伸缩(Scalable):这一点表现在很多方面。Database library本身是很精简的(少于300KB的文本空间),但它能够管理规模高达256TB的数据库。它支持高并发度,成千上万个用户可同时操纵同一个数据库。Berkeley DB能以足够小的空间占用量运行于有严格约束的嵌入式系统,也可以在高端服务器上耗用若干GB的内存和若干TB的磁盘空间。

Berkeley DB在嵌入式应用中比关系数据库和面向对象数据库要好,有以下两点原因:    

    (1)因为数据库程序库同应用程序在相同的地址空间中运行,所以数据库操作不需要进程间的通讯。在一台机器的不同进程间或在网络中不同机器间进行进程通讯所花费的开销,要远远大于函数调用的开销;

    (2)因为Berkeley DB对所有操作都使用一组API接口,因此不需要对某种查询语言进行解析,也不用生成执行计划,大大提高了运行效.





BerkeleyDB系统结构



    Berkeley DB由五个主要的子系统构成.包括: 存取管理子系统、内存池管理子系统、事务子系统、锁子系统以及日志子系统。其中存取管理子系统作为Berkeley DB数据库进程包内部核心组件,而其他子系统都存在于Berkeley DB数据库进程包的外部。  

    每个子系统支持不同的应用级别。

    1.数据存取子系统

    数据存取(Access Methods)子系统为创建和访问数据库文件提供了多种支持。Berkeley DB提供了以下四种文件存储方法:

   哈希文件、B树、定长记录(队列)和变长记录(基于记录号的简单存储方式),应用程序可以从中选择最适合的文件组织结构。

   程序员创建表时可以使用任意一种结构,并且可以在同一个应用程序中对不同存储类型的文件进行混合操作。

    在没有事务管理的情况下,该子系统中的模块可单独使用,为应用程序提供快速高效的数据存取服务。

   数据存取子系统适用于不需事务只需快速格式文件访问的应用。

    2.内存池管理子系统

    内存池(Memory pool)子系统对Berkeley DB所使用的共享缓冲区进行有效的管理。它允许同时访问数据库的多个进程或者进程的多个线程共享一个高速缓存,负责将修改后的页写回文件和为新调入的页分配内存空间。    它也可以独立于Berkeley DB系统之外,单独被应用程序使用,为其自己的文件和页分配内存空间。内存池管理子系统适用于需要灵活的、面向页的、缓冲的共享文件访问的应用。

    3.事务子系统

    事务(Transaction)子系统为Berkeley DB提供事务管理功能。它允许把一组对数据库的修改看作一个原子单位,这组操作要么全做,要么全不做。在默认的情况下,系统将提供严格的ACID事务属性,但是应用程序可以选择不使用系统所作的隔离保证。该子系统使用两段锁技术和先写日志策略来保证数据库数据的正确性和一致性。    它也可以被应用程序单独使用来对其自身的数据更新进行事务保护。事务子系统适用于需要事务保证数据的修改的应用。

    

    4.锁子系统

    锁(Locking)子系统为Berkeley DB提供锁机制,为系统提供多用户读取和单用户修改同一对象的共享控制。数据存取子系统可利用该子系统获得对页或记录的读写权限;事务子系统利用锁机制来实现多个事务的并发控制。   该子系统也可被应用程序单独采用。锁子系统适用于一个灵活的、快速的、可设置的锁管理器。

    

    5.日志子系统    

    日志(Logging)子系统采用的是先写日志的策略,用于支持事务子系统进行数据恢复,保证数据一致性。它不大可能被应用程序单独使用,只能作为事务子系统的调用模块。    以上几部分构成了整个Berkeley DB数据库系统。各部分的关系如下图所示:

    

    在这个模型中,应用程序直接调用的是数据存取子系统和事务管理子系统,这两个系统进而调用更下层的内存管理子系统、锁子系统和日志子系统。

    

    由于几个子系统相对比较独立,所以应用程序在开始的时候可以指定哪些数据管理服务将被使用。可以全部使用,也可以只用其中的一部分。例如,如果一个应用程序需要支持多用户并发操作,但不需要进行事务管理,那它就可以

只用锁子系统而不用事务。有些应用程序可能需要快速的、单用户、没有事务管理功能的B树存储结构,那么应用程序可以使锁子系统和事务子系统失效,这样就会减少开销。

BerkeleyDB存储功能概述     

    

    Berkeley DB所管理数据的逻辑组织单位是若干个独立或有一定关系的数据库(database),每个数据库由若干记录组成,这些记录全都被表示成(key,value)的形式.    如果把一组相关的(key,value)对也看作一个表的话,那么每一个数据库只允许存放一个table,这一点不同于一般的关系数据库。实际上,在Berkeley DB中所提到的“数据库”,相当于一般关系数据库系统中的表;而“key/data”对相当于关系数据库系统中的行(rows);Berkeley DB不提供关系数据库中列直接访问的功能,而是在“key/data”对中的data项中通过实际应用来封装字段(列)。

    在物理组织上,每一个数据库在创建的时候可以由应用程序根据其数据特点来选择一种合适的存储结构。可供选择的四种文件存储结构分别是:哈希文件、B树、定长记录(队列)和变长记录(基于记录号的简单存储方式)。

    一个物理的文件中可以只存放一个单独的数据库,也可以存放若干相关或不相关的数据库,而且这些数据库可以分别采用除队列之外任意不同的组织方式,以队列组织的数据库只能单独存放于一个文件,不能同其他存储类型混合存放。

    一个文件除了受最大文件长度和存储空间的约束之外,理论上可以存储任意多个数据库。因此系统定位一个数据库通常需要两个参数——“文件名”和“数据库名”,这也是Berkeley DB不同于

一般关系数据库的地方。

   Berkeley DB存储系统为应用程序提供了一系列的接口函数,用于对数据库的管理和操作。其中包括:

(1)数据库的创建、打开、关闭、删除、重命名等,以及对数据的检索和增删改操作;

      (2)提供一些附加的功能,例如读取数据库状态信息、读取所在文件的信息、读取所在数据库环境的信息、清空数据库的内容、数据库的同步备份、版本升级、提示出错信息等等;

      (3)系统还提供了游标机制,用于存取和访问成组的数据,以及对两个或多个相关数据库进行关联和等值连接操作;

      (4)系统还给出了一些接口函数用于对存取策略进行优化配置,比如应用程序可以自己设置B树的排序比较函数、每页中存放key的最少数目,哈希桶的填充因子、哈希函数、哈希表最大长度,队列的最大长度,数据库存放的字节顺序,

底层存储页的大小,内存分配函数,高速缓存的大小,定长记录的大小和填充位,变长记录所用的分隔符等等。

二、Berkeley DB的应用 

1、从官方网站http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/overview/index.html下载Berkeley
DB的安装文件及JAVA开发包。

2、在windows安装Berkeley DB,一直按下一步即可。为开发方便,安装了windows版本,正式运行时应该使用Linux版本。(设置path时出错,需要以管理员身份运行安装程序)。

3、将JAVA开发包中的jar文件放入buildpath中。主要包括je-6.0.11.jar、JEJConsole.jar、epJEJConsole.jar三个包。

测试程序:

package com.ljh.test;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test; public class BerkeleyDBUtilTest { private BerkeleyDBUtil dbUtil = null; @Before
public void setup() {
dbUtil = new BerkeleyDBUtil("D:/tmp");
} @Test
public void testWriteToDatabase() {
for (int i = 0; i < 10; i++){
dbUtil.writeToDatabase(i+"", "学生"+i, true);
}
} @Test
public void testReadFromDatabase() {
String value = dbUtil.readFromDatabase("2");
assertEquals(value, "学生2");
} @Test
public void testGetEveryItem() {
int size = dbUtil.getEveryItem().size();
assertEquals(size, 10);
} @Test
public void testDeleteFromDatabase() {
dbUtil.deleteFromDatabase("4");
assertEquals(9, dbUtil.getEveryItem().size());
} public void cleanup() {
dbUtil.closeDB();
} }

Berkeley DB的基本操作:

包括以下部分

(1)打开数据库

(2)向数据库写入数据

(3)根据Key值读取某个数据

(4)读取全量数据列表

(5)根据Key值删除某个数据

(6)关闭数据库

注意:由于各个操作可能对应同一个数据库,因此是否需要使用单例模式?

package com.ljh.test;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList; import com.sleepycat.je.Cursor;
import com.sleepycat.je.CursorConfig;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseConfig;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;
import com.sleepycat.je.LockConflictException;
import com.sleepycat.je.LockMode;
import com.sleepycat.je.OperationStatus;
import com.sleepycat.je.Transaction;
import com.sleepycat.je.TransactionConfig; public class BerkeleyDBUtil { // 数据库环境
private Environment env = null; // 数据库
private static Database frontierDatabase = null; // 数据库名
private static String dbName = "frontier_database"; public BerkeleyDBUtil(String homeDirectory) { // 1、创建EnvironmentConfig
EnvironmentConfig envConfig = new EnvironmentConfig();
envConfig.setTransactional(true);
envConfig.setAllowCreate(true); // 2、使用EnvironmentConfig配置Environment
env = new Environment(new File(homeDirectory), envConfig); // 3、创建DatabaseConfig
DatabaseConfig dbConfig = new DatabaseConfig();
dbConfig.setTransactional(true);
dbConfig.setAllowCreate(true); // 4、使用Environment与DatabaseConfig打开Database
frontierDatabase = env.openDatabase(null, dbName, dbConfig); } /*
* 向数据库中写入记录,并判断是否可以有重复数据。 传入key和value
* 若可以有重复数据,则直接使用put()即可,若不能有重复数据,则使用putNoOverwrite()。
*/
public boolean writeToDatabase(String key, String value, boolean isOverwrite) {
try {
// 设置key/value,注意DatabaseEntry内使用的是bytes数组
DatabaseEntry theKey = new DatabaseEntry(key.getBytes("UTF-8"));
DatabaseEntry theData = new DatabaseEntry(value.getBytes("UTF-8"));
OperationStatus status = null;
Transaction txn = null;
try {
// 1、Transaction配置
TransactionConfig txConfig = new TransactionConfig();
txConfig.setSerializableIsolation(true);
txn = env.beginTransaction(null, txConfig);
// 2、写入数据
if (isOverwrite) {
status = frontierDatabase.put(txn, theKey, theData);
} else {
status = frontierDatabase.putNoOverwrite(txn, theKey,
theData);
}
txn.commit();
if (status == OperationStatus.SUCCESS) {
System.out.println("向数据库" + dbName + "中写入:" + key + ","
+ value);
return true;
} else if (status == OperationStatus.KEYEXIST) {
System.out.println("向数据库" + dbName + "中写入:" + key + ","
+ value + "失败,该值已经存在");
return false;
} else {
System.out.println("向数据库" + dbName + "中写入:" + key + ","
+ value + "失败");
return false;
}
} catch (LockConflictException lockConflict) {
txn.abort();
System.out.println("向数据库" + dbName + "中写入:" + key + "," + value
+ "出现lock异常");
return false;
}
} catch (Exception e) {
// 错误处理
System.out.println("向数据库" + dbName + "中写入:" + key + "," + value
+ "出现错误"); return false;
}
} /*
* 从数据库中读出数据 传入key 返回value
*/
public String readFromDatabase(String key) {
try {
DatabaseEntry theKey = new DatabaseEntry(key.getBytes("UTF-8"));
DatabaseEntry theData = new DatabaseEntry();
Transaction txn = null;
try {
// 1、配置 Transaction相关信息
TransactionConfig txConfig = new TransactionConfig();
txConfig.setSerializableIsolation(true);
txn = env.beginTransaction(null, txConfig);
// 2、读取数据
OperationStatus status = frontierDatabase.get(txn, theKey,
theData, LockMode.DEFAULT);
txn.commit();
if (status == OperationStatus.SUCCESS) {
// 3、将字节转换成String
byte[] retData = theData.getData();
String value = new String(retData, "UTF-8");
System.out.println("从数据库" + dbName + "中读取:" + key + ","
+ value);
return value;
} else {
System.out
.println("No record found for key '" + key + "'.");
return "";
}
} catch (LockConflictException lockConflict) {
txn.abort();
System.out.println("从数据库" + dbName + "中读取:" + key + "出现lock异常");
return "";
} } catch (UnsupportedEncodingException e) {
e.printStackTrace(); return "";
}
} /*
* 遍历数据库中的所有记录,返回list
*/
public ArrayList<String> getEveryItem() {
// TODO Auto-generated method stub
System.out.println("===========遍历数据库" + dbName + "中的所有数据==========");
Cursor myCursor = null;
ArrayList<String> resultList = new ArrayList<String>();
Transaction txn = null;
try {
txn = this.env.beginTransaction(null, null);
CursorConfig cc = new CursorConfig();
cc.setReadCommitted(true);
if (myCursor == null)
myCursor = frontierDatabase.openCursor(txn, cc);
DatabaseEntry foundKey = new DatabaseEntry();
DatabaseEntry foundData = new DatabaseEntry();
// 使用cursor.getPrev方法来遍历游标获取数据
if (myCursor.getFirst(foundKey, foundData, LockMode.DEFAULT) == OperationStatus.SUCCESS) {
String theKey = new String(foundKey.getData(), "UTF-8");
String theData = new String(foundData.getData(), "UTF-8");
resultList.add(theKey);
System.out.println("Key | Data : " + theKey + " | " + theData
+ "");
while (myCursor.getNext(foundKey, foundData, LockMode.DEFAULT) == OperationStatus.SUCCESS) {
theKey = new String(foundKey.getData(), "UTF-8");
theData = new String(foundData.getData(), "UTF-8");
resultList.add(theKey);
System.out.println("Key | Data : " + theKey + " | "
+ theData + "");
}
}
myCursor.close();
txn.commit();
return resultList;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
} catch (Exception e) {
System.out.println("getEveryItem处理出现异常"); txn.abort();
if (myCursor != null) {
myCursor.close();
}
return null;
}
} /*
* 根据key值删除数据库中的一条记录
*/
public boolean deleteFromDatabase(String key) {
boolean success = false;
long sleepMillis = 0;
for (int i = 0; i < 3; i++) {
if (sleepMillis != 0) {
try {
Thread.sleep(sleepMillis);
} catch (InterruptedException e) {
e.printStackTrace();
}
sleepMillis = 0;
}
Transaction txn = null;
try {
// 1、使用cursor.getPrev方法来遍历游标获取数据
TransactionConfig txConfig = new TransactionConfig();
txConfig.setSerializableIsolation(true);
txn = env.beginTransaction(null, txConfig);
DatabaseEntry theKey;
theKey = new DatabaseEntry(key.getBytes("UTF-8")); //2、删除数据 并提交
OperationStatus res = frontierDatabase.delete(txn, theKey);
txn.commit();
if (res == OperationStatus.SUCCESS) {
System.out.println("从数据库" + dbName + "中删除:" + key);
success = true;
return success;
} else if (res == OperationStatus.KEYEMPTY) {
System.out.println("没有从数据库" + dbName + "中找到:" + key + "。无法删除");
} else {
System.out.println("删除操作失败,由于" + res.toString());
}
return false;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return false;
} catch (LockConflictException lockConflict) {
System.out.println("删除操作失败,出现lockConflict异常");
sleepMillis = 1000; continue;
} finally {
if (!success) {
if (txn != null) {
txn.abort();
}
}
}
}
return false;
} public void closeDB() {
if (frontierDatabase != null) {
frontierDatabase.close();
}
if (env != null) {
env.close();
}
} }

Berkeley DB基础教程的更多相关文章

  1. Berkeley DB基础教程 分类: H3_NUTCH 2014-05-29 15:21 2212人阅读 评论(0) 收藏

    一.Berkeley DB的介绍 (1)Berkeley DB是一个嵌入式数据库,它适合于管理海量的.简单的数据.如Google使用其来保存账户信息,Heritrix用其来保存froniter. (2 ...

  2. BDB (Berkeley DB)数据库简单介绍(转载)

    近期要使用DBD,于是搜了下相关的资料,先贴个科普性的吧: 转自http://www.javaeye.com/topic/202990 DB综述DB最初开发的目的是以新的HASH訪问算法来取代旧的hs ...

  3. Oracle Berkeley DB Java 版

    Oracle Berkeley DB Java 版是一个开源的.可嵌入的事务存储引擎,是完全用 Java 编写的.它充分利用 Java 环境来简化开发和部署.Oracle Berkeley DB Ja ...

  4. 新浪研发中心: Berkeley DB 使用经验总结

    http://blog.sina.com.cn/s/blog_502c8cc40100yqkj.html NoSQL是现在互联网Web2.0时代备受关注的技术之一,被用来存储大量的非关系型的数据.Be ...

  5. 「JAVA」:Berkeley DB的JAVA连接

    Berkeley DB是一个嵌入式的数据库,它适合于管理海量的.简单的数据.关键字/数据(key/value)是Berkeley DB用来进行数据管理的基础.每个key/value构成了一条记录,而整 ...

  6. Berkeley DB 使用

    http://www.ibm.com/developerworks/cn/linux/l-embdb/index.html UNIX/LINUX平台下的数据库种类非常多,参考资料1中 列举了其中的大部 ...

  7. BDB (Berkeley DB)简要数据库(转载)

    使用最近DBD.然后搜了下相关资料,首先公布的是一门科学: 转会http://www.javaeye.com/topic/202990 DB综述DB最初开发的目的是以新的HASH訪问算法来取代旧的hs ...

  8. 免费数据库(SQLite、Berkeley DB、PostgreSQL、MySQL、Firebird、mSQL、MSDE、DB2 Express-C、Oracle XE)

    SQLite数据库是中小站点CMS的最佳选择 SQLite 是一个类似Access的轻量级数据库系统,但是更小.更快.容量更大,并发更高.为什么说 SQLite 最适合做 CMS (内容管理系统)呢? ...

  9. Spring Cloud Alibaba基础教程:Nacos的集群部署

    继续说说生产环境的Nacos搭建,通过上一篇<Spring Cloud Alibaba基础教程:Nacos的数据持久化>的介绍,我们已经知道Nacos对配置信息的存储原理,在集群搭建的时候 ...

随机推荐

  1. hdu1860

    #include<iostream> #include <stdio.h> #include<string> #include <iomanip> us ...

  2. JavaScript函数学习要点总结(一)

    1.函数的最大作用是提供代码复用: 2.JavaScript函数是弱类型语言,定义函数时既不要声明函数的返回值,也不要声明函数的参数列表类型: 语法如下: function functionName( ...

  3. css元素隐藏(display:none和visibility:hidden)

    在css中, display:none和visibility:hidden都能够使元素隐藏.但是两者所带来的效果完全不同. css  display:none 当使用该样式的时候,HTML元素的宽高等 ...

  4. Rectangle and Square

    Description Little Petya very much likes rectangles and especially squares. Recently he has received ...

  5. 实用AutoHotkey功能展示

    AutoHotkey是什么 AutoHotkey是一个自动化脚本语言. AutoHotkey有什么用 可以让你用热键操控一切,操作电脑就像在表演魔术 我的口号 AutoHotkey!用过都说好! Au ...

  6. node.js及相关组件安装

    第一步:下载安装文件(下载地址:官网http://www.nodejs.org/download/ )第二步:安装nodejs(双击直接安装) 安装完成后使用命令行查看版本信息,出现版本号说明安装成功 ...

  7. 给FPGA初学者的建议——不要浮躁(转)

    原作者:http://hi.baidu.com/zhoubin7020 作为FPGA新人常常在论坛上问,用什么语言啊,用什么软件啊,用那个公司的芯片等问题.我个人认为学习FPGA和学习单片机有相同的道 ...

  8. SPI 四种模式

    SPI时钟极性CPOL, = 0表示在没有数据传输时为低电平,= 1表示没有数据传输时为高电平. SPI时钟相位CPHA,= 0表示时钟的第一个沿更新数据.第二个沿锁存数据,= 1表示时钟的第一个沿锁 ...

  9. Theme.AppCompat.Light报错

    style文件中的Theme.AppCompat.Light报错,Error retrieving parent for item: No resource found that matches th ...

  10. Poj 2187 Beauty Contest_旋转凸包卡壳

    题意:给你n个坐标,求最远的两点距离 思路:用凸包算法求处,各个定点,再用旋转凸包卡壳 #include <iostream> #include <cstdio> #inclu ...