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