Berkeley DB: Open Source Embedded Database

xiaoxiao2021-03-05  20

Although this C / S-based relational relational database system based on Mysql represents the mainstream of current database applications, it does not meet the needs of all applications. Sometimes we need to just a simple disk-based database system. This not only avoids the installation of large database servers, but also simplifies the design of the database application. Berkeley DB is based on this idea.

Introduction to Berkeley DB

Berkeley DB is an open source Embedded database management system that provides high-performance data management services for applications. Applying it that programmers only need to call some simple APIs to complete access and management of data. Unlike commonly used database management systems (such as mysql and oracle, etc.) vary, in Berkeley DB, there is no concept of a database server. The application does not need to establish a network connection with the database service, but through the Berkeley DB function library embedded in the program to complete the save, query, modification, and deletion of the data.

Berkeley DB provides a practical API interface for many programming languages, including C, C , Java, Perl, TCL, Python, and PHP. All the operations related to the database are all responsible for uniformity by the Berkeley DB function library. This is a function of accessing the database at the same time whether multiple processes in the system, or multiple threads in the same process. The underlying data lock, transaction logs and storage management are implemented in the Berkeley DB function library. They are completely transparent to the app. As the saying goes: "The sparrow is a small fifty and full." The Berkeley DB function library is only about 300kB, but it can manage up to 256TB of data, and in many aspects of performance can compete with commercial grade database systems. In the case of concurrent operation of the data, Berkeley DB can easily delegate thousands of users access the same database at the same time. In addition, if you want to perform database management on resource-limited embedded systems, Berkeley DB may be the only correct choice.

Berkeley DB has a unique advantage in many ways as an embedded database system. First, due to its application and database management system running in the same process space, the cumbersome process can be avoided when performing data operation, so that the overhead of the communication is naturally reduced to the extremely low degree. Second, Berkeley DB uses a simple function call interface to complete all database operations, not the SQL language that is often used in the database system. This avoids the overhead required to parse and process the structured query language.

basic concepts

Berkeley DB simplifies the operation mode of the database, and introduces some new basic concepts, making access and managing databases relatively simple. Before using the library provided by Berkeley DB, it is necessary to understand the following basic concepts before writing database applications.

Keywords and data

Keywords (KEY) and Data (DATA) are the basis of Berkeley DB for database management, and the key / data pair (see Table 1) composed of these two constitute a basic structural unit in the database, and the entire database is actually The upper is made up of many such structural units. By using this manner, developers can access the corresponding data when using the API provided by the Berkeley DB to access the database.

KeyData SportfootballFruitoNGedrinkBeer

Table 1 Key / Data

If you want to save "Sport" and "Football" in the first row to the Berkeley DB database, you can call the data saved interface provided by the Berkeley DB Function Library. At this point, "Sport" and "Football" will be viewed as keywords and data, respectively. If you need to retrieve this data from the database, you can use "Sport" as a keyword. At this point, the interface function provided by Berkeley DB returns "Football" corresponding to the corresponding data. Keywords and data are represented by a simple structure called DBT in Berkeley DB. In fact, both can be any length of binary data, and the role of DBT is mainly saved corresponding memory address and its length, and its structure is as follows:

Typedef struct {

Void * Data;

U_INT32_T SIZE;

U_INT32_T ULEN;

U_INT32_T DLEN;

U_INT32_T DOFF;

U_INT32_T FLAGS;

} DBT;

When using Berkeley DB, it is default, a keyword corresponds to a data, but in fact, the database can be configured to configure a keyword corresponding to multiple data.

Object handle

Most functions defined by the Berkeley DB Library Follow the same call principle: first create a structure, and then call certain methods in this structure. From the perspective of programming, this is very similar to object-oriented design principles, that is, one instance of an object is created, and then call certain methods of the instance. For this reason, Berkeley DB introduces the concept of the object handle to represent the instantiated structure, and the member function in the structure is called the handle.

The introduction of the object handle allows the programmer to complete access and operation of the Berkeley DB database completely, even if the currently used structured language is currently used. For example, for the operation of opening a database, the Open function provided by the object handle of DB can be called, and the prototype is as follows:

INT DB-> Open (DB * DB, DB_TXN * TXNID, Const Char * File,

Const Char * Database, DBTYPE TYPE, U_INT32_T FLAGS, INT MODE

Error Handling How to make unified processing for errors in any function library is a problem that needs to be considered. All functions provided by Berkeley DB follow the same error handling principles, that is, the function is successfully executed, and the words are returned, otherwise the non-zero value is returned. For system errors (such as insufficient disk space and not enough access, it is a standard value; for non-system errors, it returns a specific error code. For example, if there is no data corresponding to a particular key in the database, an error occurs when the data is retrieved through the keyword. At this time, the return value of the function will be db_notfound, indicating that the requested keyword does not appear in the database. All standard Errno values ​​are greater than zero, and special error codes defined by Berkeley DB are less than zero. The programmer is required to remember that all the error codes is neither actual, because Berkeley DB provides corresponding functions to obtain an error description corresponding to the error code. Once there is an error, just call the DB_STRERROR () function first to get the error description information, then call DB-> Err () or db-> errx () to easily output the formatted error message.

Applying a unified programming interface Use the functions of Berkeley DB to perform database access and management. In most cases, you can complete the most basic operations with a unified interface criteria. Open the database to open the database to do two steps: First call the DB_CREATE () function to create an instance of the DB structure, then call the DB-> Open () function to complete the real open operation. Berkeley DB puts all the operations of the database in a structure called DB. The role of the db_create () function is to create a structure whose prototype is as follows: typedef struct__db DB;

INT DB_CREATE (DB ** DBP, DB_ENV * DBENV, U_INT32_T FLAGS);

Open the file saved on the disk is done by the DB-> open () function, whose prototype is as follows:

INT DB-> Open (DB * DB, DB_TXN * TXNID, Const Char * File,

Const Char * Database, DBTYPE TYPE, U_INT32_T FLAGS, INT MODE

The following code demonstrates how to create a DB object handle and how to open the Database file:

#include

#include

#include

#include

#include

#define Database "Demo.db"

/ * The program of the following program code is the same * /

int main ()

{DB * DBP;

int R;

IF ((Ret = DB_CREATE (& DBP, NULL, 0))! = 0) {

FPRINTF (stderr, "db_create:% s / n", db_strerror (re));

Exit (1);

}

IF ((Ret = DBP-> Open (DBP, NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664))! = 0) {

DBP-> Err (DBP, RET, "% S", Database;

Exit (1);

}

}

The code first calls the DB_CREATE () function to create a DB object handle. Variable DBP will become a database handle after the call is successful, and it can complete the configuration or access to the underlying database. Next, call the db-> open () function Open the database file, the parameter "database" indicates that the corresponding disk file name is demo.db; the parameter "db_btree" indicates the data structure used by the database under the bottom of the database; and the parameter "db_create" and "0664" indicates that a new database file is created when the database file does not exist, and the attribute value of the file is set to 0664.

The error handling is the routine check that must be turned on when the database is turned on, which can be done by calling the DB-> ERR () function. The parameter "RET" is the error code returned after calling the Berkeley DB function, and the remaining parameters are used to display structured error messages.

adding data

Adding data to the Berkeley DB database can be done by calling the DB-> PUT () function, the prototype is as follows:

INT DB-> PUT (DB * DB, DB_TXN * TXNID, DBT * KEY, DBT * DATA, U_INT32_T FLAGS);

The following code demonstrates how to add new data to the database:

int main ()

{DB * DBP;

DBT Key, Data;

int R;

IF ((Ret = DB_CREATE (& DBP, NULL, 0))! = 0) {FPRINTF (stderr, "db_create:% s / n", db_strerror (re));

Exit (1);

}

IF ((RET = DBP-> Open (DBP,

NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664))! = 0) {

DBP-> Err (DBP, RET, "% S", Database;

Exit (1);

}

MEMSET (& Key, 0, Sizeof (Key);

MEMSET (& Data, 0, SIZEOF (DATA);

Key.Data = "Sport";

Key.Size = SizeOf ("Sport");

Data.Data = "football";

Data.size = SizeOf ("Football");

IF ((RET = DBP-> PUT (DBP, NULL, & Key, & Data, 0)) == 0)

Printf ("DB:% S: Key Stored./N", (Char *) Key.Data);

Else

DBP-> Err (DBP, RET, "DB-> PUT");

}

The code first declares two DBT structural variables and fills with strings "Sport" and "Football" separately. They are then passed as keywords and data to DB-> PUT () functions used to add data. The DBT structure is almost used in all functions related to data access.

When adding data to the database, most applications will use overlay principles for existing data for a given keyword. That is, if a "Sport / Basketball" pair has been saved in the database, call the DB-> Put () function again Add a "Sport / Football" pair, then the previously saved data will be overwritten. However, Berkeley DB allows the parameter "DB_NOOVERWRITE" to be specified when the DB-> Put () function is called, and the declaration does not cover the data already existing in the database, and its code is as follows:

IF ((Ret = DBP-> PUT (DBP, NULL, & Key, & Data, DB_NOOVERWRITE) == 0)

Printf ("DB:% S: Key Stored./N", (Char *) Key.Data);

Else

DBP-> Err (DBP, RET, "DB-> PUT");

Once the "DB_NOOVERWRITE" tag is given, if the DB-> Put () function found that the keyword given during the execution has existed in the database, it is unable to successfully add the key / data to the database, so Returns the error number "DB_KEYEXIST".

Search data

Retrieving data from the Berkeley DB database can be done by calling the DB-> GET () function, the prototype is as follows:

INT DB-> GET (DB * DB, DB_TXN * TXNID, DBT * KEY, DBT * DATA, U_INT32_T FLAGS);

The following code demonstrates how to retrieve the required data from the database:

int main ()

{DB * DBP;

DBT Key, Data;

int R;

IF ((Ret = DB_CREATE (& DBP, NULL, 0))! = 0) {

FPRINTF (stderr, "db_create:% s / n", db_strerror (re)); exit (1);

}

IF ((RET = DBP-> Open (DBP,

NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664))! = 0) {

DBP-> Err (DBP, RET, "% S", Database;

Exit (1);

}

MEMSET (& Key, 0, Sizeof (Key);

MEMSET (& Data, 0, SIZEOF (DATA);

Key.Data = "Sport";

Key.Size = SizeOf ("Sport");

IF ((RET = DBP-> GET (DBP, NULL, & Key, & Data, 0)) == 0)

Printf ("DB:% S: Key Retrieved: Data WAS% s. / N",

(char *) Key.Data, (char *) data.data);

Else

DBP-> Err (DBP, RET, "DB-> GET");

}

The code also declares two DBT structural variables, and calls the MEMSET () function to empty them. Although Berkeley DB does not enhances the requirements before performing data operation, it will be emptied to improve code quality, but it is recommended to perform emptying operations. When performing data retrieval, it is essential for processing the return value of the DB-> GET () function because it carries information such as retrieval operations. The return value of the DB-> GET () function is listed below:

◆ 0 The function call is successful, the specified keyword is found;

◆ DB_NOTFOUND function calls success, but the specified keyword is not found;

◆ More than 0 function call failed, there may be a system error.

delete data

Removing data from the Berkeley DB database can be done by calling the DB-> Del () function, the prototype is as follows:

INT DB-> DEL (DB * DB, DB_TXN * TXNID, DBT * KEY, U_INT32_T FLAGS);

The following code demonstrates how to delete data from the database:

int main ()

{DB * DBP;

DBT Key;

int R;

IF ((Ret = DB_CREATE (& DBP, NULL, 0))! = 0) {

FPRINTF (stderr, "db_create:% s / n", db_strerror (re));

Exit (1);

}

IF ((RET = DBP-> Open (DBP,

NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664))! = 0) {

DBP-> Err (DBP, RET, "% S", Database;

Exit (1);

}

MEMSET (& Key, 0, Sizeof (Key);

Key.Data = "Sport";

Key.Size = SizeOf ("Sport");

IF ((RET = DBP-> Del (DBP, NULL, & Key, 0)) == 0)

Printf ("DB:% S: Key Was Deleted./N", (char *) key.data);

Else

DBP-> Err (DBP, RET, "DB-> DEL");

}

Deleting data simply gives the corresponding keyword without indicating the corresponding data. Close the database

For a complete database operation, shutting down the database is an indispensable part. This is because Berkeley DB needs to rely on the underlying buffer mechanism, that is, the modified data may all be written on disk only when the database is turned off, and the resources it occupies can also be truly released. . Turning off the database is done by calling the db-> close () function, its prototype is as follows:

INT DB-> Close (DB * DB, U_INT32_T FLAGS);

The following code demonstrates how to turn off the database when needed:

int main ()

{DB * DBP;

DBT Key, Data;

int RET, T_RET;

IF ((Ret = DB_CREATE (& DBP, NULL, 0))! = 0) {

FPRINTF (stderr, "db_create:% s / n", db_strerror (re));

Exit (1);

}

IF ((RET = DBP-> Open (DBP,

NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664))! = 0) {

DBP-> Err (DBP, RET, "% S", Database;

Goto ERR;

}

MEMSET (& Key, 0, Sizeof (Key);

MEMSET (& Data, 0, SIZEOF (DATA);

Key.Data = "Sport";

Key.Size = SizeOf ("Sport");

IF ((RET = DBP-> GET (DBP, NULL, & Key, & Data, 0)) == 0)

Printf ("DB:% S: Key Retrieved: Data WAS% s. / N",

(char *) Key.Data, (char *) data.data);

Else

DBP-> Err (DBP, RET, "DB-> GET");

IF ((t_ret = dbp-> close (dbp, 0))! = 0 && rett == 0)

RET = T_RET;

exit (re);

}

summary

Berkeley DB This embedded database system is very simple. It doesn't have a database server concept, nor does it require a complex SQL statement, all of which can be done through function calls, which is ideal for applications that need to be simple to manage data.

转载请注明原文地址:https://www.9cbs.com/read-38888.html

New Post(0)