###

Berkeley DB Reference Guide:
  Berkeley DB Concurrent Data Store Applications

# Building Berkeley DB Concurrent Data Store applications

It is often desirable to have concurrent read-write access to a database when there is no need for full recoverability or transaction semantics. For this class of applications, Berkeley DB provides an interface supporting deadlock free, multiple-reader/single writer access to the database. This means that, at any instant in time, there may be either multiple readers accessing data or a single writer modifying data. The application is entirely unaware of which is happening, and Berkeley DB implements the necessary locking and blocking to ensure this behavior.

In order to create Berkeley DB Concurrent Data Store applications, you must first initialize an environment by calling DBENV->open. You must specify the DB_INIT_CDB and DB_INIT_MPOOL flags to that interface. It is an error to specify any of the other DBENV->open subsystem or recovery configuration flags, e.g., DB_INIT_LOCK, DB_INIT_TXN or DB_RECOVER.

All databases must, of course, be created in this environment, by using the db_create interface and specifying the correct environment as an argument.

The Berkeley DB access method calls used to support concurrent access are unchanged from the normal access method calls, with one exception: the DB->cursor interface. In Berkeley DB Concurrent Data Store, each cursor must encapsulate the idea of being used for read-only access or for read-write access. There may only be one read-write cursor active at any one time. When your application creates a cursor, if that cursor will ever be used for writing, the DB_WRITECURSOR flag must be specified when the cursor is created.

No deadlock detector needs to be run in a Berkeley DB Concurrent Data Store database environment.

Only a single thread of control may write the database at a time. For this reason care must be taken to ensure that applications do not inadvertently block themselves causing the application to hang, unable to proceed. Some common mistakes include:

1. Leaving a cursor open while issuing a DB->put or DB->del access method call.

2. Attempting to open a cursor for read-write access while already holding a cursor open for read-write access.

3. Not testing Berkeley DB error return codes (if any cursor operation returns an unexpected error, that cursor should be closed).

4. By default, Berkeley DB Concurrent Data Store does locking on a per-database basis. For this reason, accessing multiple databases in different orders in different threads or processes, or leaving cursors open on one database while accessing another database, can cause an application to hang. If this behavior is a requirement for the application, Berkeley DB can be configured to do locking on an environment wide basis. See the DB_CDB_ALLDB flag of the DBENV->set_flags function for more information.

Note that it is correct operation for two different threads of control (actual threads or processes) to have multiple read-write cursors open, or for one thread to issue a DB->put call while another thread has a read-write cursor open, and it is only a problem if these things are done within a single thread of control.

Copyright Sleepycat Software