Development Environment
Windows XP Profession,Visual Studio C++ 2005
Concept
1、 Berkeley DB是嵌入式数据库系统,支持几乎所有的现代操作系统。
2、 由一个个文件组成,文件名为XXX.DB,一个文件中可以含有一个到多个DB。
3、 Berkeley DB不支持SQL、存储过程和触发器等关系数据库的高级特性。
4、 Database(DBT)就相同于关系数据库中的Table,它的key/data 对就相当于关系数据表的主键和其它n-1列,因为你可以在data中存入任意类型的数据,比如一个结构体。
5、 游标(Cursor,DBC),就是一个关于特定记录的遍历器,在处理多重记录(duplicate record,多条记录key相同,而data不同)时使用它尤为方便,且效率高(称为bulk get,一次获取一批记录)。
6、 数据库环境(DB_ENV),为Berkeley DB的高级特性,就是多个Database的包装器,它提供诸如日志恢复、多线程、事务处理和高性能支持等服务。
7、 数据访问算法(Database Access Method)——数据在硬盘上存储和操作的方法。Berkeley DB支持B+树、Hash、Recno和Queue算法。
Begin to Use Berkeley DB
添加Berkeley db的include目录为Application的include路径,添加其lib目录为Application的lib引用路径,这样将Berkeley DB的lib和我们的Application编译为一个程序,令其“嵌入”我们的程序中。
Choose Database Access Method
Access Method | Description | Choosing Occasion |
B+树 | 关键字有序存储,并且其结构能随数据的插入和删除进行动态调整。为了代码的简单,Berkeley DB没有实现对关键字的前缀码压缩。B+树支持对数据查询、插入、删除的常数级速度。关键字可以为任意的数据结构。 | 1、 当Key为复杂类型时。 2、 当Key有序时。 |
Hash | DB中实际使用的是扩展线性HASH算法(extended linear hashing),可以根据HASH表的增长进行适当的调整。关键字可以为任意的数据结构。 | 1、 当Key为复杂类型。 2、 当数据较大且key随机分布时。 |
Recno | 要求每一个记录都有一个逻辑纪录号,逻辑纪录号由算法本身生成。相当于关系数据库中的自动增长字段。Recho建立在B+树算法之上,提供了一个存储有序数据的接口。记录的长度可以为定长或不定长。 | 1、 当key为逻辑记录号时。 2、 当非高并发的情况下。 |
Queue | 和Recno方式接近, 只不过记录的长度为定长。数据以定长记录方式存储在队列中,插入操作把记录插入到队列的尾部,相比之下插入速度是最快的。 | 1、 1、当key为逻辑记录号时。 2、 定长记录。 3、 高并发的情况下。 |
Open Database
使用Db.open来打开一个数据库。打开数据库有多种方式,常用的有:
Open Flag | Description |
DB_CREATE | 如果数据库不存在,则创建之。 |
DB_EXCL | 如果数据库存在,则返回失败。只和DB_CREATE一起使用才有意义。 |
DB_RDONLY | 以只读的方式打开数据库。 |
代码示例:
#include <db_cxx.h> ... Db db(NULL, 0); // Instantiate the Db object u_int32_t oFlags = DB_CREATE; // Open flags; try { // Open the database db.open(NULL, // Transaction pointer "my_db.db", // Database file name NULL, // Optional logical database name DB_BTREE, // Database access method oFlags, // Open flags 0); // File mode (using defaults) // DbException is not subclassed from std::exception, so // need to catch both of these. } catch(DbException &e) { // Error handling code goes here } catch(std::exception &e) { // Error handling code goes here } |
如果需要使用Berkeley DB的高级功能,可以在DbEnv(环境)中打开Database:
#include <db_cxx.h> ... u_int32_t env_flags = DB_CREATE; // If the environment does not // exist, create it. u_int32_t db_flags = DB_CREATE; // If the database does not // exist, create it. std::string envHome("/export1/testEnv"); std::string dbName("mydb.db"); DbEnv myEnv(0); Db *myDb; try { myEnv.open(envHome.c_str(), env_flags, 0); myDb = new Db(&myEnv, 0); myDb->open(NULL, dbName.c_str(), NULL, DB_BTREE, db_flags, 0); } catch(DbException &e) { std::cerr << "Error opening database environment: " << envHome << " and database " << dbName << std::endl; std::cerr << e.what() << std::endl; exit( -1 ); } catch(std::exception &e) { std::cerr << "Error opening database environment: " << envHome << " and database " << dbName << std::endl; std::cerr << e.what() << std::endl; exit( -1 ); } |
Close Database
关闭数据库很简单,只需要使用Db.close(0)来关闭db:
#include <db_cxx.h> ... Db db(NULL, 0); // Database open and access operations happen here. try { // Close the database db.close(0); // DbException is not subclassed from std::exception, so // need to catch both of these. } catch(DbException &e) { // Error handling code goes here } catch(std::exception &e) { // Error handling code goes here } |
当在DbEnv中打开数据库时,关闭此DbEnv中的所有的Db后,必须关闭此DbEnv:
try { if (myDb != NULL) { myDb->close(0); } myEnv.close(0); } catch(DbException &e) { std::cerr << "Error closing database environment: " << envHome << " or database " << dbName << std::endl; std::cerr << e.what() << std::endl; exit( -1 ); } catch(std::exception &e) { std::cerr << "Error closing database environment: " << envHome << " or database " << dbName << std::endl; std::cerr << e.what() << std::endl; exit( -1 ); } |
在操作数据(添加、修改和删除数据)时,都是在内存中进行的,并没有写到磁盘中,而只有当我们调用Db.close(0)方法后,才将内存中的数据写入磁盘中。如果不想关闭数据库而又想把数据写入磁盘的话,可以调用Db.sync(0)方法,及时将数据写入磁盘可以降低发生DB crash而导致数据丢失的危险的几率。