mirror of
https://github.com/yasuhirokimura/db18
synced 2026-06-08 18:29:23 +00:00
266 lines
14 KiB
HTML
266 lines
14 KiB
HTML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||
<title>Chapter 10. Berkeley DB Data Store and Concurrent Data Store Applications</title>
|
||
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
|
||
<meta name="generator" content="DocBook XSL Stylesheets V1.73.2" />
|
||
<link rel="start" href="index.html" title="Berkeley DB Programmer's Reference Guide" />
|
||
<link rel="up" href="index.html" title="Berkeley DB Programmer's Reference Guide" />
|
||
<link rel="prev" href="env_faq.html" title="Environment FAQ" />
|
||
<link rel="next" href="cam_fail.html" title="Handling failure in Data Store and Concurrent Data Store applications" />
|
||
</head>
|
||
<body>
|
||
<div xmlns="" class="navheader">
|
||
<div class="libver">
|
||
<p>Library Version 18.1.40</p>
|
||
</div>
|
||
<table width="100%" summary="Navigation header">
|
||
<tr>
|
||
<th colspan="3" align="center">Chapter 10. Berkeley DB Data Store and Concurrent Data Store Applications</th>
|
||
</tr>
|
||
<tr>
|
||
<td width="20%" align="left"><a accesskey="p" href="env_faq.html">Prev</a> </td>
|
||
<th width="60%" align="center"> </th>
|
||
<td width="20%" align="right"> <a accesskey="n" href="cam_fail.html">Next</a></td>
|
||
</tr>
|
||
</table>
|
||
<hr />
|
||
</div>
|
||
<div class="chapter" lang="en" xml:lang="en">
|
||
<div class="titlepage">
|
||
<div>
|
||
<div>
|
||
<h2 class="title"><a id="cam"></a>Chapter 10. Berkeley DB Data Store and Concurrent Data Store Applications</h2>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="toc">
|
||
<p>
|
||
<b>Table of Contents</b>
|
||
</p>
|
||
<dl>
|
||
<dt>
|
||
<span class="sect1">
|
||
<a href="cam.html#cam_intro">Concurrent Data Store
|
||
introduction</a>
|
||
</span>
|
||
</dt>
|
||
<dt>
|
||
<span class="sect1">
|
||
<a href="cam_fail.html">Handling failure in Data Store and Concurrent Data Store applications</a>
|
||
</span>
|
||
</dt>
|
||
<dt>
|
||
<span class="sect1">
|
||
<a href="cam_app.html">Architecting Data Store and Concurrent Data Store applications</a>
|
||
</span>
|
||
</dt>
|
||
<dt>
|
||
<span class="sect1">
|
||
<a href="gsg_bdb.html">Quick Start Guide</a>
|
||
</span>
|
||
</dt>
|
||
<dd>
|
||
<dl>
|
||
<dt>
|
||
<span class="sect2">
|
||
<a href="gsg_bdb.html#gsg_ds">Data Store Environment</a>
|
||
</span>
|
||
</dt>
|
||
<dt>
|
||
<span class="sect2">
|
||
<a href="gsg_bdb.html#gsg_cds">Concurrent Data Store Environment</a>
|
||
</span>
|
||
</dt>
|
||
<dt>
|
||
<span class="sect2">
|
||
<a href="gsg_bdb.html#gsg_tds">Transactional Data Store Environment</a>
|
||
</span>
|
||
</dt>
|
||
</dl>
|
||
</dd>
|
||
</dl>
|
||
</div>
|
||
<div class="sect1" lang="en" xml:lang="en">
|
||
<div class="titlepage">
|
||
<div>
|
||
<div>
|
||
<h2 class="title" style="clear: both"><a id="cam_intro"></a>Concurrent Data Store
|
||
introduction</h2>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<p>
|
||
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 interfaces 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.
|
||
</p>
|
||
<p>
|
||
To create Berkeley DB Concurrent Data Store applications,
|
||
you must first initialize an environment by calling <a href="../api_reference/C/envopen.html" class="olink">DB_ENV->open()</a>.
|
||
You must specify the <a href="../api_reference/C/envopen.html#envopen_DB_INIT_CDB" class="olink">DB_INIT_CDB</a> and <a href="../api_reference/C/envopen.html#envopen_DB_INIT_MPOOL" class="olink">DB_INIT_MPOOL</a> flags
|
||
to that method. It is an error to specify any of the other
|
||
<a href="../api_reference/C/envopen.html" class="olink">DB_ENV->open()</a> subsystem or recovery configuration flags, for
|
||
example, <a href="../api_reference/C/envopen.html#envopen_DB_INIT_LOCK" class="olink">DB_INIT_LOCK</a>, <a href="../api_reference/C/envopen.html#envopen_DB_INIT_TXN" class="olink">DB_INIT_TXN</a> or <a href="../api_reference/C/envopen.html#envopen_DB_RECOVER" class="olink">DB_RECOVER</a> All
|
||
databases must, of course, be created in this environment by
|
||
using the <a href="../api_reference/C/dbcreate.html" class="olink">db_create()</a> function or <a href="../api_reference/CXX/db.html" class="olink">Db</a> constructor,
|
||
and specifying the environment as an argument.
|
||
</p>
|
||
<p>
|
||
Berkeley DB performs appropriate locking so that safe
|
||
enforcement of the deadlock-free,
|
||
multiple-reader/single-writer semantic is transparent to the
|
||
application. However, a basic understanding of Berkeley DB
|
||
Concurrent Data Store locking behavior is helpful when writing
|
||
Berkeley DB Concurrent Data Store applications.
|
||
</p>
|
||
<p>
|
||
Berkeley DB Concurrent Data Store avoids deadlocks without
|
||
the need for a deadlock detector by performing all locking on
|
||
an entire database at once (or on an entire environment in the
|
||
case of the <a href="../api_reference/C/envset_flags.html#set_flags_DB_CDB_ALLDB" class="olink">DB_CDB_ALLDB</a> flag), and by ensuring that at any
|
||
given time only one thread of control is allowed to
|
||
simultaneously hold a read (shared) lock and attempt to
|
||
acquire a write (exclusive) lock.
|
||
</p>
|
||
<p>
|
||
All open Berkeley DB cursors hold a read lock, which serves
|
||
as a guarantee that the database will not change beneath them;
|
||
likewise, all non-cursor <a href="../api_reference/C/dbget.html" class="olink">DB->get()</a> operations temporarily
|
||
acquire and release a read lock that is held during the actual
|
||
traversal of the database. Because read locks will not
|
||
conflict with each other, any number of cursors in any number
|
||
of threads of control may be open simultaneously, and any
|
||
number of <a href="../api_reference/C/dbget.html" class="olink">DB->get()</a> operations may be concurrently in
|
||
progress.
|
||
</p>
|
||
<p>
|
||
To enforce the rule that only one thread of control at a
|
||
time can attempt to upgrade a read lock to a write lock,
|
||
however, Berkeley DB must forbid multiple cursors from
|
||
attempting to write concurrently. This is done using the
|
||
<a href="../api_reference/C/dbcursor.html#cursor_DB_WRITECURSOR" class="olink">DB_WRITECURSOR</a> flag to the <a href="../api_reference/C/dbcursor.html" class="olink">DB->cursor()</a> method. This is the
|
||
only difference between access method calls in Berkeley DB
|
||
Concurrent Data Store and in the other Berkeley DB products.
|
||
The <a href="../api_reference/C/dbcursor.html#cursor_DB_WRITECURSOR" class="olink">DB_WRITECURSOR</a> flag causes the newly created cursor to
|
||
be a "write" cursor; that is, a cursor capable of performing
|
||
writes as well as reads. Only cursors thus created are
|
||
permitted to perform write operations (either deletes or
|
||
puts), and only one such cursor can exist at any given
|
||
time.
|
||
</p>
|
||
<p>
|
||
Any attempt to create a second write cursor or to perform a
|
||
non-cursor write operation while a write cursor is open will
|
||
block until that write cursor is closed. Read cursors may open
|
||
and perform reads without blocking while a write cursor is
|
||
extant. However, any attempts to actually perform a write,
|
||
either using the write cursor or directly using the <a href="../api_reference/C/dbput.html" class="olink">DB->put()</a> or
|
||
<a href="../api_reference/C/dbdel.html" class="olink">DB->del()</a> methods, will block until all read cursors are closed.
|
||
This is how the multiple-reader/single-writer semantic is
|
||
enforced, and prevents reads from seeing an inconsistent
|
||
database state that may be an intermediate stage of a write
|
||
operation.
|
||
</p>
|
||
<p>
|
||
By default, Berkeley DB Concurrent Data Store does locking
|
||
on a per-database basis. For this reason, using cursors to
|
||
access 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 should be configured to do locking on an
|
||
environment-wide basis. See the <a href="../api_reference/C/envset_flags.html#set_flags_DB_CDB_ALLDB" class="olink">DB_CDB_ALLDB</a> flag of the
|
||
<a href="../api_reference/C/envset_flags.html" class="olink">DB_ENV->set_flags()</a> method for more information.
|
||
</p>
|
||
<p>
|
||
With these behaviors, Berkeley DB can guarantee
|
||
deadlock-free concurrent database access, so that multiple
|
||
threads of control are free to perform reads and writes
|
||
without needing to handle synchronization themselves or having
|
||
to run a deadlock detector. Berkeley DB has no direct
|
||
knowledge of which cursors belong to which threads, so some
|
||
care must be taken to ensure that applications do not
|
||
inadvertently block themselves, causing the application to
|
||
hang and be unable to proceed.
|
||
</p>
|
||
<p>
|
||
As a consequence of the Berkeley DB Concurrent Data Store
|
||
locking model, the following sequences of operations will
|
||
cause a thread to block itself indefinitely:
|
||
</p>
|
||
<div class="orderedlist">
|
||
<ol type="1">
|
||
<li>
|
||
Keeping a cursor open while issuing a <a href="../api_reference/C/dbput.html" class="olink">DB->put()</a> or
|
||
<a href="../api_reference/C/dbdel.html" class="olink">DB->del()</a> access method call.
|
||
</li>
|
||
<li>
|
||
Attempting to open a write cursor while another
|
||
cursor is already being held open by the same thread of
|
||
control. Note that it is correct operation for one thread
|
||
of control to attempt to open a write cursor or to perform
|
||
a non-cursor write (<a href="../api_reference/C/dbput.html" class="olink">DB->put()</a> or <a href="../api_reference/C/dbdel.html" class="olink">DB->del()</a>) while a write
|
||
cursor is already active in another thread. It is only a
|
||
problem if these things are done within a single thread of
|
||
control -- in which case that thread will block and never
|
||
be able to release the lock that is blocking
|
||
it.
|
||
</li>
|
||
<li>
|
||
Not testing Berkeley DB error return codes (if any
|
||
cursor operation returns an unexpected error, that cursor
|
||
must still be closed).
|
||
</li>
|
||
</ol>
|
||
</div>
|
||
<p>
|
||
If the application needs to open multiple cursors in a
|
||
single thread to perform an operation, it can indicate to
|
||
Berkeley DB that the cursor locks should not block each other
|
||
by creating a Berkeley DB Concurrent Data Store <span class="bold"><strong>group</strong></span>, using <a href="../api_reference/C/envcdsgroup_begin.html" class="olink">DB_ENV->cdsgroup_begin()</a>.
|
||
This creates a locker ID that is shared by all cursors opened
|
||
in the group.
|
||
</p>
|
||
<p>
|
||
Berkeley DB Concurrent Data Store groups use a <a href="../api_reference/C/txn.html" class="olink">TXN</a> handle
|
||
to indicate the shared locker ID to Berkeley DB calls, and
|
||
call <a href="../api_reference/C/txncommit.html" class="olink">DB_TXN->commit()</a> to end the group. This is a convenient way to
|
||
pass the locked ID to the calls where it is needed, but should
|
||
not be confused with the real transactional semantics provided
|
||
by Berkeley DB Transactional Data Store. In particular,
|
||
Berkeley DB Concurrent Data Store groups do not provide any
|
||
abort or recovery facilities, and have no impact on durability
|
||
of operations.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div class="navfooter">
|
||
<hr />
|
||
<table width="100%" summary="Navigation footer">
|
||
<tr>
|
||
<td width="40%" align="left"><a accesskey="p" href="env_faq.html">Prev</a> </td>
|
||
<td width="20%" align="center"> </td>
|
||
<td width="40%" align="right"> <a accesskey="n" href="cam_fail.html">Next</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td width="40%" align="left" valign="top">Environment FAQ </td>
|
||
<td width="20%" align="center">
|
||
<a accesskey="h" href="index.html">Home</a>
|
||
</td>
|
||
<td width="40%" align="right" valign="top"> Handling failure in Data Store and Concurrent Data Store applications</td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
</body>
|
||
</html>
|