1<!--$Id: am_conv.so,v 10.24 2003/04/02 16:15:32 bostic Exp $-->
2<!--Copyright (c) 1997,2008 Oracle.  All rights reserved.-->
3<!--See the file LICENSE for redistribution information.-->
4<html>
5<head>
6<title>Berkeley DB Reference Guide: Berkeley DB Transactional Data Store locking conventions</title>
7<meta name="description" content="Berkeley DB: An embedded database programmatic toolkit.">
8<meta name="keywords" content="embedded,database,programmatic,toolkit,btree,hash,hashing,transaction,transactions,locking,logging,access method,access methods,Java,C,C++">
9</head>
10<body bgcolor=white>
11<a name="2"><!--meow--></a>
12<table width="100%"><tr valign=top>
13<td><b><dl><dt>Berkeley DB Reference Guide:<dd>Locking Subsystem</dl></b></td>
14<td align=right><a href="../lock/cam_conv.html"><img src="../../images/prev.gif" alt="Prev"></a><a href="../toc.html"><img src="../../images/ref.gif" alt="Ref"></a><a href="../lock/nondb.html"><img src="../../images/next.gif" alt="Next"></a>
15</td></tr></table>
16<p align=center><b>Berkeley DB Transactional Data Store locking conventions</b></p>
17<p>All Berkeley DB access methods follow the same conventions for locking
18database objects.  Applications that do their own locking and also do
19locking via the access methods must be careful to adhere to these
20conventions.</p>
21<p>Whenever a Berkeley DB database is opened, the <a href="../../api_c/db_class.html">DB</a> handle is assigned
22a unique locker ID.  Unless transactions are specified, that ID is used
23as the locker for all calls that the Berkeley DB methods make to the lock
24subsystem.  In order to lock a file,  pages in the file, or records in
25the file, we must create a unique ID that can be used as the object to
26be locked in calls to the lock manager.  Under normal operation, that
27object is a 28-byte value created by the concatenation of a unique file
28identifier, a page or record number, and an object type (page or record).</p>
29<p>In a transaction-protected environment, database create and delete
30operations are recoverable and single-threaded.  This single-threading
31is achieved using a single lock for the entire environment that must be
32acquired before beginning a create or delete operation.  In this case,
33the object on which Berkeley DB will lock is a 4-byte unsigned integer with
34a value of 0.</p>
35<p>If applications are using the lock subsystem directly while they are
36also using locking via the access methods, they must take care not to
37inadvertently lock objects that happen to be equal to the unique file
38IDs used to lock files.  This is most easily accomplished by using a
39lock object with a length different from the values used by Berkeley DB.</p>
40<p>All the access methods other than Queue use standard read/write locks
41in a simple multiple-reader/single writer page-locking scheme.  An
42operation that returns data (for example, <a href="../../api_c/db_get.html">DB-&gt;get</a> or
43<a href="../../api_c/dbc_get.html">DBcursor-&gt;get</a>) obtains a read lock on all the pages accessed while
44locating the requested record.   When an update operation is requested
45(for example, <a href="../../api_c/db_put.html">DB-&gt;put</a> or <a href="../../api_c/dbc_del.html">DBcursor-&gt;del</a>), the page containing
46the updated (or new) data is write-locked.  As read-modify-write cycles
47are quite common and are deadlock-prone under normal circumstances, the
48Berkeley DB interfaces allow the application to specify the <a href="../../api_c/dbc_get.html#DB_RMW">DB_RMW</a>
49flag, which causes operations to immediately obtain a write lock, even
50though they are only reading the data.  Although this may reduce
51concurrency somewhat, it reduces the probability of deadlock.  In the
52presence of transactions, page locks are held until transaction commit.</p>
53<p>The Queue access method does not hold long-term page locks.  Instead,
54page locks are held only long enough to locate records or to change
55metadata on a page, and record locks are held for the appropriate
56duration.  In the presence of transactions, record locks are held until
57transaction commit.  For Berkeley DB operations, record locks are held until
58operation completion; for <a href="../../api_c/dbc_class.html">DBC</a> operations, record locks are held
59until subsequent records are returned or the cursor is closed.</p>
60<p>Under non-transaction operations, the access methods do not normally
61hold locks across calls to the Berkeley DB interfaces.  The one exception to
62this rule is when cursors are used.  Because cursors maintain a position
63in a file, they must hold locks across calls; in fact, they will hold
64a lock until the cursor is closed.</p>
65<p>In this mode, the assignment of locker IDs to <a href="../../api_c/db_class.html">DB</a> and cursor
66handles is complicated.  If the <a href="../../api_c/env_open.html#DB_THREAD">DB_THREAD</a> option was specified
67when the <a href="../../api_c/db_class.html">DB</a> handle was opened, each use of a <a href="../../api_c/db_class.html">DB</a> has its
68own unique locker ID, and each cursor is assigned its own unique locker
69ID when it is created, so <a href="../../api_c/db_class.html">DB</a> handle and cursor operations can
70all conflict with one another.  (This is because when  Berkeley DB handles
71may be shared by multiple threads of control the Berkeley DB library cannot
72identify which operations are performed by which threads of control,
73and it must ensure that two different threads of control are not
74simultaneously modifying the same data structure.  By assigning each
75<a href="../../api_c/db_class.html">DB</a> handle and cursor its own locker, two threads of control
76sharing a handle cannot inadvertently interfere with each other.)</p>
77<p>This has important implications.  If a single thread of control opens
78two cursors, uses a combination of cursor and non-cursor operations, or
79begins two separate transactions, the operations are performed on behalf
80of different lockers.  Conflicts that arise between these different
81lockers may not cause actual deadlocks, but can, in fact, permanently
82block the thread of control.  For example, assume that an application
83creates a cursor and uses it to read record A.  Now, assume a second
84cursor is opened, and the application attempts to write record A using
85the second cursor.  Unfortunately, the first cursor has a read lock, so
86the second cursor cannot obtain its write lock.  However, that read lock
87is held by the same thread of control, so the read lock can never be
88released if we block waiting for the write lock.  This might appear to
89be a deadlock from the application's perspective, but Berkeley DB cannot
90identify it as such because it has no knowledge of which lockers belong
91to which threads of control.  For this reason, application designers
92are encouraged to close cursors as soon as they are done with them.</p>
93<p>If the <a href="../../api_c/env_open.html#DB_THREAD">DB_THREAD</a> option was not specified when the <a href="../../api_c/db_class.html">DB</a>
94handle was opened, all uses of the <a href="../../api_c/db_class.html">DB</a> handle and all cursors
95created using that handle will use the same locker ID for all
96operations.  In this case, if a single thread of control opens two
97cursors or uses a combination of cursor and non-cursor operations, these
98operations are performed on behalf of the same locker, and so cannot
99deadlock or block the thread of control.</p>
100<p>Complicated operations that require multiple cursors (or combinations
101of cursor and non-cursor operations) can be performed in two ways.
102First, they may be performed within a transaction, in which case all
103operations lock on behalf of the designated transaction.  Second, they
104may be performed using a local <a href="../../api_c/db_class.html">DB</a> handle, although, as
105<a href="../../api_c/db_open.html">DB-&gt;open</a> operations are relatively slow, this may not be a good
106idea.  Finally, the <a href="../../api_c/dbc_dup.html">DBcursor-&gt;dup</a> function duplicates a cursor, using
107the same locker ID as the originating cursor.  There is no way to
108achieve this duplication functionality through the <a href="../../api_c/db_class.html">DB</a> handle
109calls, but any <a href="../../api_c/db_class.html">DB</a> call can be implemented by one or more calls
110through a cursor.</p>
111<p>When the access methods use transactions, many of these problems disappear.
112The transaction ID is used as the locker ID for all operations performed
113on behalf of the transaction.  This means that the application may open
114multiple cursors on behalf of the same transaction and these cursors will
115all share a common locker ID.  This is safe because transactions cannot
116span threads of control, so the library knows that two cursors in the same
117transaction cannot modify the database concurrently.</p>
118<table width="100%"><tr><td><br></td><td align=right><a href="../lock/cam_conv.html"><img src="../../images/prev.gif" alt="Prev"></a><a href="../toc.html"><img src="../../images/ref.gif" alt="Ref"></a><a href="../lock/nondb.html"><img src="../../images/next.gif" alt="Next"></a>
119</td></tr></table>
120<p><font size=1>Copyright (c) 1996,2008 Oracle.  All rights reserved.</font>
121</body>
122</html>
123