1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3<html xmlns="http://www.w3.org/1999/xhtml">
4  <head>
5    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
6    <title>The Locking Subsystem</title>
7    <link rel="stylesheet" href="gettingStarted.css" type="text/css" />
8    <meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
9    <link rel="home" href="index.html" title="Getting Started with Berkeley DB Transaction Processing" />
10    <link rel="up" href="txnconcurrency.html" title="Chapter��4.��Concurrency" />
11    <link rel="previous" href="blocking_deadlocks.html" title="Locks, Blocks, and Deadlocks" />
12    <link rel="next" href="isolation.html" title="Isolation" />
13  </head>
14  <body>
15    <div class="navheader">
16      <table width="100%" summary="Navigation header">
17        <tr>
18          <th colspan="3" align="center">The Locking Subsystem</th>
19        </tr>
20        <tr>
21          <td width="20%" align="left"><a accesskey="p" href="blocking_deadlocks.html">Prev</a>��</td>
22          <th width="60%" align="center">Chapter��4.��Concurrency</th>
23          <td width="20%" align="right">��<a accesskey="n" href="isolation.html">Next</a></td>
24        </tr>
25      </table>
26      <hr />
27    </div>
28    <div class="sect1" lang="en" xml:lang="en">
29      <div class="titlepage">
30        <div>
31          <div>
32            <h2 class="title" style="clear: both"><a id="lockingsubsystem"></a>The Locking Subsystem</h2>
33          </div>
34        </div>
35        <div></div>
36      </div>
37      <p>
38            In order to allow concurrent operations, DB provides the locking
39            subsystem. This subsystem provides inter- and intra- process
40            concurrency mechanisms. It is extensively used by DB concurrent
41            applications, but it can also be generally used for non-DB
42            resources.
43        </p>
44      <p>
45            This section describes the locking subsystem as it is used to
46            protect DB resources. In particular, issues on configuration are
47            examined here. For information on using the locking subsystem to
48            manage non-DB resources, see the
49            <i class="citetitle">Berkeley DB Programmer's Reference Guide</i>.
50        </p>
51      <div class="sect2" lang="en" xml:lang="en">
52        <div class="titlepage">
53          <div>
54            <div>
55              <h3 class="title"><a id="configuringlock"></a>Configuring the Locking Subsystem</h3>
56            </div>
57          </div>
58          <div></div>
59        </div>
60        <p>
61                You initialize the locking subsystem by specifying
62                    <span>
63                        <tt class="literal">DB_INIT_LOCK</tt> to the
64                        
65                        <tt class="methodname">DbEnv::open()</tt>
66                        method.
67                    </span>
68                    
69            </p>
70        <p>
71                Before opening your environment, you can configure various
72                maximum values for your locking subsystem. Note that these
73                limits can only be configured before the environment is
74                opened. Also, these methods configure the entire environment,
75                not just a specific environment handle.
76            </p>
77        <p>
78                Finally, each bullet below identifies the 
79                <tt class="filename">DB_CONFIG</tt> file parameter that can be used
80                to specify the specific locking limit. If used, these
81                <tt class="filename">DB_CONFIG</tt> file parameters override any
82                value that you might specify using the environment handle. 
83            </p>
84        <p>
85                The limits that you can configure are as follows:
86            </p>
87        <div class="itemizedlist">
88          <ul type="disc">
89            <li>
90              <p>
91                        The maximum number of lockers
92                        supported by the environment. This value is used by
93                        the environment when it is opened to estimate the amount
94                        of space that it should allocate for various internal
95                        data structures. By default, 1,000 lockers are
96                        supported.
97                    </p>
98              <p>
99                        To configure this value, use the 
100                        <span>
101                            
102                            <tt class="methodname">DbEnv::set_lk_max_lockers()</tt>
103                        method.
104                        </span>
105                        
106                    </p>
107              <p>
108                        As an alternative to this method, you can configure this
109                        value using the <tt class="filename">DB_CONFIG</tt> file's
110                        <tt class="literal">set_lk_max_lockers</tt> parameter.
111                    </p>
112            </li>
113            <li>
114              <p>
115                        The maximum number of locks supported by the environment.
116                        By default, 1,000 locks are supported.
117                    </p>
118              <p>
119                        To configure this value, use the 
120                        <span>
121                            
122                            <tt class="methodname">DbEnv::set_lk_max_locks()</tt>
123                        method.
124                        </span>
125                        
126                    </p>
127              <p>
128                        As an alternative to this method, you can configure this
129                        value using the <tt class="filename">DB_CONFIG</tt> file's
130                        <tt class="literal">set_lk_max_locks</tt> parameter.
131                    </p>
132            </li>
133            <li>
134              <p>
135                        The maximum number of locked objects supported by the environment.
136                        By default, 1,000 objects can be locked.
137                    </p>
138              <p>
139                        To configure this value, use the 
140                        <span>
141                            
142                            <tt class="methodname">DbEnv::set_lk_max_objects()</tt>
143                        method.
144                        </span>
145                        
146                    </p>
147              <p>
148                        As an alternative to this method, you can configure this
149                        value using the <tt class="filename">DB_CONFIG</tt> file's
150                        <tt class="literal">set_lk_max_objects</tt> parameter.
151                    </p>
152            </li>
153          </ul>
154        </div>
155        <p>
156                For a definition of lockers, locks, and locked objects, see
157                <a href="blocking_deadlocks.html#lockresources">Lock Resources</a>.
158            </p>
159        <p>
160                For example, to configure the maximum number of locks that your
161                environment can use:
162            </p>
163        <pre class="programlisting">#include "db_cxx.h"
164
165...
166                                                                                                                                  
167int main(void)
168{
169    u_int32_t env_flags = DB_CREATE     |  // If the environment does not
170                                           // exist, create it.
171                          DB_INIT_LOCK  |  // Initialize locking
172                          DB_INIT_LOG   |  // Initialize logging
173                          DB_INIT_MPOOL |  // Initialize the cache
174                          DB_THREAD     |  // Free-thread the env handle.
175                          DB_INIT_TXN;     // Initialize transactions
176                                                                                                                                  
177    std::string envHome("/export1/testEnv");
178    DbEnv myEnv(0);
179
180    try {
181
182        // Configure max locks
183        myEnv.set_lk_max_locks(envp, 5000);
184
185        myEnv.open(envHome.c_str(), env_flags, 0);
186
187    } catch(DbException &amp;e) {
188        std::cerr &lt;&lt; "Error opening database environment: "
189                  &lt;&lt; envHome &lt;&lt; std::endl;
190        std::cerr &lt;&lt; e.what() &lt;&lt; std::endl;
191        return (EXIT_FAILURE);
192    }
193
194    try {
195        myEnv.close(0);
196    } catch(DbException &amp;e) {
197        std::cerr &lt;&lt; "Error closing database environment: "
198                &lt;&lt; envHome &lt;&lt; std::endl;
199        std::cerr &lt;&lt; e.what() &lt;&lt; std::endl;
200        return (EXIT_FAILURE);
201    }
202
203    return (EXIT_SUCCESS);
204} </pre>
205      </div>
206      <div class="sect2" lang="en" xml:lang="en">
207        <div class="titlepage">
208          <div>
209            <div>
210              <h3 class="title"><a id="configdeadlkdetect"></a>Configuring Deadlock Detection</h3>
211            </div>
212          </div>
213          <div></div>
214        </div>
215        <p>
216                In order for DB to know that a deadlock has occurred,
217                some mechanism must be used to perform deadlock
218                detection. There are three ways that deadlock detection can
219                occur:
220            </p>
221        <div class="orderedlist">
222          <ol type="1">
223            <li>
224              <p>
225                        Allow DB to internally detect deadlocks as they
226                        occur.
227                    </p>
228              <p>
229                        To do this, you use
230                            
231                            <span><tt class="methodname">DbEnv::set_lk_detect()</tt>.</span>
232                            
233                            This method causes DB to walk its internal lock table 
234                            looking for a deadlock whenever a lock request
235                            is blocked. This method also identifies how DB decides which lock
236                            requests are rejected when deadlocks are detected. For example,
237                            DB can decide to reject the lock request for the transaction
238                            that has the most number of locks, the least number of locks,
239                            holds the oldest lock, holds the most number of write locks, and
240                            so forth (see the API reference documentation for a complete
241                            list of the lock detection policies).
242                    </p>
243              <p>
244                        You can call this method at any time during your application's
245                        lifetime, but typically it is used before you open your environment.
246                    </p>
247              <p>
248                        Note that how you want DB to decide which thread of control should break a deadlock is
249                        extremely dependent on the nature of your application. It is not unusual for some performance
250                        testing to be required in order to make this determination. That said, a transaction that is
251                        holding the maximum number of locks is usually indicative of the transaction that has performed
252                        the most amount of work. Frequently you will not want a transaction that has performed a lot of
253                        work to abandon its efforts and start all over again. It is not therefore uncommon for
254                        application developers to initially select the transaction with the <span class="emphasis"><em>minimum</em></span>
255                        number of write locks to break the deadlock.
256                    </p>
257              <p>
258                        Using this mechanism for deadlock detection means
259                        that your application will never have to wait on a
260                        lock before discovering that a deadlock has
261                        occurred. However, walking the lock table every
262                        time a lock request is blocked can be expensive
263                        from a performance perspective.
264                    </p>
265            </li>
266            <li>
267              <p>
268                        Use a dedicated thread or external process to perform
269                        deadlock detection. Note that this thread must be
270                        performing no other database operations beyond deadlock
271                        detection.
272                    </p>
273              <p>
274                        To externally perform lock detection, you can use
275                        either the
276                            
277                            <tt class="methodname">DbEnv::lock_detect()</tt>
278                            
279                           method, or use the
280                           <span><b class="command">db_deadlock</b></span> command line
281                           utility. This method (or command) causes DB to walk the
282                           lock table looking for deadlocks. 
283                    </p>
284              <p>
285                        Note that like
286                            
287                            <span><tt class="methodname">DbEnv::set_lk_detect()</tt>,</span>
288                            
289                        you also use this method (or command line utility)
290                        to identify which lock requests are rejected in the
291                        event that a deadlock is detected.
292                    </p>
293              <p>
294                        Applications that perform deadlock detection in
295                        this way typically run deadlock detection between every few
296                        seconds and a minute. This means that your
297                        application may have to wait to be notified of a
298                        deadlock, but you also save the overhead of walking
299                        the lock table every time a lock request is blocked.
300                    </p>
301            </li>
302            <li>
303              <p>
304                        Lock timeouts.
305                    </p>
306              <p>
307                        You can configure your locking subsystem such that
308                        it times out any lock that is not released within a
309                        specified amount of time. To do this, use the
310                            
311                            <span><tt class="methodname">DbEnv::set_timeout()</tt></span>
312                            
313                        method. 
314                            Note that lock timeouts are only checked when a
315                            lock request is blocked or when deadlock
316                            detection is otherwise performed. Therefore, a lock can have timed out and still be held for
317                            some length of time until DB has a reason to examine its locking tables.
318                    </p>
319              <p>
320                        Be aware that extremely long-lived transactions, or
321                        operations that hold locks for a long time, may be
322                        inappropriately timed out before the transaction or
323                        operation has a chance to complete. You should
324                        therefore use this mechanism only if you know your
325                        application will hold locks for very short periods
326                        of time.
327                    </p>
328            </li>
329          </ol>
330        </div>
331        <p>
332                For example, to configure your application such that DB
333                checks the lock table for deadlocks every time a lock
334                request is blocked:
335            </p>
336        <pre class="programlisting">#include "db_cxx.h"
337
338...
339                                                                                                                                  
340int main(void)
341{
342    u_int32_t env_flags = DB_CREATE     |  // If the environment does not
343                                           // exist, create it.
344                          DB_INIT_LOCK  |  // Initialize locking
345                          DB_INIT_LOG   |  // Initialize logging
346                          DB_INIT_MPOOL |  // Initialize the cache
347                          DB_THREAD     |  // Free-thread the env handle
348                          DB_INIT_TXN;     // Initialize transactions
349
350    std::string envHome("/export1/testEnv");
351    DbEnv myEnv(0);
352
353    try {
354
355        // Configure db to perform deadlock detection internally, and to
356        // choose the transaction that has performed the least amount 
357        // of writing to break the deadlock in the event that one 
358        // is detected.
359        myEnv.set_lk_detect(DB_LOCK_MINWRITE);
360        myEnv.open(envHome.c_str(), env_flags, 0);
361     
362        // From here, you open your databases, proceed with your 
363        // database operations, and respond to deadlocks as 
364        // is normal (omitted for brevity).
365
366        
367        ...</pre>
368        <p>
369        Finally, the following command line call causes
370        deadlock detection to be run against the
371        environment contained in <tt class="literal">/export/dbenv</tt>. The 
372        transaction with the youngest lock is chosen to break the
373        deadlock:
374    </p>
375        <pre class="programlisting">&gt; /usr/local/db_install/bin/db_deadlock -h /export/dbenv -a y</pre>
376        <p>
377        For more information, see the
378        <a href="http://www.oracle.com/technology/documentation/berkeley-db/db/utility/db_deadlock.html" target="_top">
379            <tt class="literal">db_deadlock</tt> reference documentation.
380        </a>
381    </p>
382      </div>
383      <div class="sect2" lang="en" xml:lang="en">
384        <div class="titlepage">
385          <div>
386            <div>
387              <h3 class="title"><a id="deadlockresolve"></a>Resolving Deadlocks</h3>
388            </div>
389          </div>
390          <div></div>
391        </div>
392        <p>
393                When DB determines that a deadlock has occurred, it will
394                select a thread of control to resolve the deadlock and then 
395                    
396                    <span>
397                        throws <tt class="literal">DbDeadlockException</tt> in that
398                        thread.
399                    </span>
400                    
401                    
402                 If a deadlock is detected, the thread must:
403            </p>
404        <div class="orderedlist">
405          <ol type="1">
406            <li>
407              <p>
408                        Cease all read and write operations.
409                    </p>
410            </li>
411            <li>
412              <p>
413                        Close all open cursors.
414                    </p>
415            </li>
416            <li>
417              <p>
418                        Abort the transaction.
419                    </p>
420            </li>
421            <li>
422              <p>
423                        Optionally retry the operation. If your application
424                        retries deadlocked operations, the new attempt must
425                        be made using a new transaction.
426                    </p>
427            </li>
428          </ol>
429        </div>
430        <div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
431          <h3 class="title">Note</h3>
432          <p>
433                    If a thread has deadlocked, it may not make any
434                    additional database calls using the handle that has
435                    deadlocked.
436                </p>
437        </div>
438        <p>
439                For example:
440            </p>
441        <pre class="programlisting">// retry_count is a counter used to identify how many times
442// we've retried this operation. To avoid the potential for 
443// endless looping, we won't retry more than MAX_DEADLOCK_RETRIES 
444// times.
445
446// txn is a transaction handle.
447// key and data are DBT handles. Their usage is not shown here.
448while (retry_count &lt; MAX_DEADLOCK_RETRIES) {
449    try {
450        envp-&gt;txn_begin(NULL, txn, 0);
451        dbp-&gt;put(txn, &amp;key, &amp;data, 0);
452        txn-&gt;commit(0);
453        return (EXIT_SUCCESS);
454    } catch (DbDeadlockException &amp;de) {
455        try {
456            // Abort the transaction and increment the 
457            // retry counter
458            txn-&gt;abort();
459            retry_count++;
460            // If we've retried too many times, log it and exit
461            if (retry_count &gt;= MAX_DEADLOCK_RETRIES) {
462                    envp-&gt;errx("Exceeded retry limit. Giving up.");
463                    return (EXIT_FAILURE);
464            }
465        } catch (DbException &amp;ae) {
466            envp-&gt;err(ae.get_errno(), "txn abort failed.");
467            return (EXIT_FAILURE);    
468        }
469    } catch (DbException &amp;e) {
470        try {
471            // For a generic error, log it and abort.
472            envp-&gt;err(e.get_errno(), "Error putting data.");
473            txn-&gt;abort();
474        } catch (DbException &amp;ae) {
475            envp-&gt;err(ae.get_errno(), "txn abort failed.");
476            return (EXIT_FAILURE);    
477        }
478    }
479} </pre>
480      </div>
481    </div>
482    <div class="navfooter">
483      <hr />
484      <table width="100%" summary="Navigation footer">
485        <tr>
486          <td width="40%" align="left"><a accesskey="p" href="blocking_deadlocks.html">Prev</a>��</td>
487          <td width="20%" align="center">
488            <a accesskey="u" href="txnconcurrency.html">Up</a>
489          </td>
490          <td width="40%" align="right">��<a accesskey="n" href="isolation.html">Next</a></td>
491        </tr>
492        <tr>
493          <td width="40%" align="left" valign="top">Locks, Blocks, and Deadlocks��</td>
494          <td width="20%" align="center">
495            <a accesskey="h" href="index.html">Home</a>
496          </td>
497          <td width="40%" align="right" valign="top">��Isolation</td>
498        </tr>
499      </table>
500    </div>
501  </body>
502</html>
503