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                        <code class="methodname">DB_ENV-&gt;open()</code>
82                        
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                            <code class="methodname">DB_ENV-&gt;set_lk_max_lockers()</code>
119                            
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                            <code class="methodname">DB_ENV-&gt;set_lk_max_locks()</code>
139                            
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                            <code class="methodname">DB_ENV-&gt;set_lk_max_objects()</code>
159                            
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 &lt;stdio.h&gt;
181#include &lt;stdlib.h&gt;
182
183#include "db.h"
184
185int
186main(void)
187{
188    int ret, ret_c;
189    u_int32_t env_flags;
190    DB_ENV *envp;
191    const char *db_home_dir = "/tmp/myEnvironment";
192    
193    envp = NULL;
194
195    /* Open the environment */
196    ret = db_env_create(&amp;envp, 0);
197    if (ret != 0) {
198        fprintf(stderr, "Error creating environment handle: %s\n",
199            db_strerror(ret));
200        return (EXIT_FAILURE);
201    }
202                                                                                                                                  
203    env_flags = DB_CREATE     |  /* If the environment does not
204                                  * exist, create it. */
205                DB_INIT_LOCK  |  /* Initialize locking */
206                DB_INIT_LOG   |  /* Initialize logging */
207                DB_INIT_MPOOL |  /* Initialize the cache */
208                DB_THREAD     |  /* Free-thread the env handle. */
209                DB_INIT_TXN;     /* Initialize transactions */
210                                                                                                                                  
211    /* Configure max locks */
212    ret = envp-&gt;set_lk_max_locks(envp, 5000);
213    if (ret != 0) {
214        fprintf(stderr, "Error configuring locks: %s\n",
215            db_strerror(ret));
216        goto err;
217    }
218
219    /* Open the environment. */
220    ret = envp-&gt;open(envp, db_home_dir, env_flags, 0);
221    if (ret != 0) {
222        fprintf(stderr, "Error opening environment: %s\n",
223            db_strerror(ret));
224        goto err;
225    }
226
227err:
228    /* Close the environment */
229    if (envp != NULL) {
230        ret_c = envp-&gt;close(envp, 0);
231        if (ret_c != 0) {
232            fprintf(stderr, "environment close failed: %s\n",
233                db_strerror(ret_c));
234            ret = ret_c;
235        }
236    }
237
238    return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
239} </pre>
240      </div>
241      <div class="sect2" lang="en" xml:lang="en">
242        <div class="titlepage">
243          <div>
244            <div>
245              <h3 class="title"><a id="configdeadlkdetect"></a>Configuring Deadlock Detection</h3>
246            </div>
247          </div>
248        </div>
249        <p>
250                In order for DB to know that a deadlock has occurred,
251                some mechanism must be used to perform deadlock
252                detection. There are three ways that deadlock detection can
253                occur:
254            </p>
255        <div class="orderedlist">
256          <ol type="1">
257            <li>
258              <p>
259                        Allow DB to internally detect deadlocks as they
260                        occur.
261                    </p>
262              <p>
263                        To do this, you use
264                            <span><code class="methodname">DB_ENV-&gt;set_lk_detect()</code>.</span>
265                            
266                            
267                            This method causes DB to walk its internal lock table 
268                            looking for a deadlock whenever a lock request
269                            is blocked. This method also identifies how DB decides which lock
270                            requests are rejected when deadlocks are detected. For example,
271                            DB can decide to reject the lock request for the transaction
272                            that has the most number of locks, the least number of locks,
273                            holds the oldest lock, holds the most number of write locks, and
274                            so forth (see the API reference documentation for a complete
275                            list of the lock detection policies).
276                    </p>
277              <p>
278                        You can call this method at any time during your application's
279                        lifetime, but typically it is used before you open your environment.
280                    </p>
281              <p>
282                        Note that how you want DB to decide which thread of control should break a deadlock is
283                        extremely dependent on the nature of your application. It is not unusual for some performance
284                        testing to be required in order to make this determination. That said, a transaction that is
285                        holding the maximum number of locks is usually indicative of the transaction that has performed
286                        the most amount of work. Frequently you will not want a transaction that has performed a lot of
287                        work to abandon its efforts and start all over again. It is not therefore uncommon for
288                        application developers to initially select the transaction with the <span class="emphasis"><em>minimum</em></span>
289                        number of write locks to break the deadlock.
290                    </p>
291              <p>
292                        Using this mechanism for deadlock detection means
293                        that your application will never have to wait on a
294                        lock before discovering that a deadlock has
295                        occurred. However, walking the lock table every
296                        time a lock request is blocked can be expensive
297                        from a performance perspective.
298                    </p>
299            </li>
300            <li>
301              <p>
302                        Use a dedicated thread or external process to perform
303                        deadlock detection. Note that this thread must be
304                        performing no other database operations beyond deadlock
305                        detection.
306                    </p>
307              <p>
308                        To externally perform lock detection, you can use
309                        either the
310                            <code class="methodname">DB_ENV-&gt;lock_detect()</code>
311                            
312                            
313                           method, or use the
314                           <span class="command"><strong>db_deadlock</strong></span> command line
315                           utility. This method (or command) causes DB to walk the
316                           lock table looking for deadlocks. 
317                    </p>
318              <p>
319                        Note that like
320                            <span><code class="methodname">DB_ENV-&gt;set_lk_detect()</code>,</span>
321                            
322                            
323                        you also use this method (or command line utility)
324                        to identify which lock requests are rejected in the
325                        event that a deadlock is detected.
326                    </p>
327              <p>
328                        Applications that perform deadlock detection in
329                        this way typically run deadlock detection between every few
330                        seconds and a minute. This means that your
331                        application may have to wait to be notified of a
332                        deadlock, but you also save the overhead of walking
333                        the lock table every time a lock request is blocked.
334                    </p>
335            </li>
336            <li>
337              <p>
338                        Lock timeouts.
339                    </p>
340              <p>
341                        You can configure your locking subsystem such that
342                        it times out any lock that is not released within a
343                        specified amount of time. To do this, use the
344                            <span><code class="methodname">DB_ENV-&gt;set_timeout()</code></span>
345                            
346                            
347                        method. 
348                            Note that lock timeouts are only checked when a
349                            lock request is blocked or when deadlock
350                            detection is otherwise performed. Therefore, a lock can have timed out and still be held for
351                            some length of time until DB has a reason to examine its locking tables.
352                    </p>
353              <p>
354                        Be aware that extremely long-lived transactions, or
355                        operations that hold locks for a long time, may be
356                        inappropriately timed out before the transaction or
357                        operation has a chance to complete. You should
358                        therefore use this mechanism only if you know your
359                        application will hold locks for very short periods
360                        of time.
361                    </p>
362            </li>
363          </ol>
364        </div>
365        <p>
366                For example, to configure your application such that DB
367                checks the lock table for deadlocks every time a lock
368                request is blocked:
369            </p>
370        <pre class="programlisting">#include &lt;stdio.h&gt;
371#include &lt;stdlib.h&gt;
372
373#include "db.h"
374
375int
376main(void)
377{
378    int ret, ret_c;
379    u_int32_t db_flags, env_flags;
380    DB *dbp;
381    DB_ENV *envp;
382    DB_TXN *txn;
383    const char *db_home_dir = "/tmp/myEnvironment";
384    const char *file_name = "mydb.db";
385    
386    envp = NULL;
387
388    /* Open the environment */
389    ret = db_env_create(&amp;envp, 0);
390    if (ret != 0) {
391        fprintf(stderr, "Error creating environment handle: %s\n",
392            db_strerror(ret));
393        return (EXIT_FAILURE);
394    }
395                                                                                                                                  
396    env_flags = DB_CREATE     |  /* If the environment does not
397                                  * exist, create it. */
398                DB_INIT_LOCK  |  /* Initialize locking */
399                DB_INIT_LOG   |  /* Initialize logging */
400                DB_INIT_MPOOL |  /* Initialize the cache */
401                DB_THREAD     |  /* Free-thread the env handle. */
402                DB_INIT_TXN;     /* Initialize transactions */
403
404    /*
405     * Configure db to perform deadlock detection internally, and to
406     * choose the transaction that has performed the least amount of writing
407     * to break the deadlock in the event that one is detected.
408     */
409    ret = envp-&gt;set_lk_detect(envp, DB_LOCK_MINWRITE);
410    if (ret != 0) {
411        fprintf(stderr, "Error setting lk detect: %s\n",
412            db_strerror(ret));
413        goto err;
414    }
415
416    ret = envp-&gt;open(envp, db_home_dir, env_flags, 0);
417    if (ret != 0) {
418        fprintf(stderr, "Error opening environment: %s\n",
419            db_strerror(ret));
420        goto err;
421    }
422
423    /* 
424     * From here, you open your databases, proceed with your 
425     * database operations, and respond to deadlocks as 
426     * is normal (omitted for brevity).
427     */
428
429     ...  </pre>
430        <p>
431        Finally, the following command line call causes
432        deadlock detection to be run against the
433        environment contained in <code class="literal">/export/dbenv</code>. The 
434        transaction with the youngest lock is chosen to break the
435        deadlock:
436    </p>
437        <pre class="programlisting">&gt; /usr/local/db_install/bin/db_deadlock -h /export/dbenv -a y</pre>
438        <p>
439        For more information, see the
440        <a class="ulink" href="http://www.oracle.com/technology/documentation/berkeley-db/db/utility/db_deadlock.html" target="_top">
441            <code class="literal">db_deadlock</code> reference documentation.
442        </a>
443    </p>
444      </div>
445      <div class="sect2" lang="en" xml:lang="en">
446        <div class="titlepage">
447          <div>
448            <div>
449              <h3 class="title"><a id="deadlockresolve"></a>Resolving Deadlocks</h3>
450            </div>
451          </div>
452        </div>
453        <p>
454                When DB determines that a deadlock has occurred, it will
455                select a thread of control to resolve the deadlock and then 
456                    <span>
457                        return <code class="literal">DB_LOCK_DEADLOCK</code> to that
458                        thread.
459                    </span>
460                    
461                    
462                    
463                 If a deadlock is detected, the thread must:
464            </p>
465        <div class="orderedlist">
466          <ol type="1">
467            <li>
468              <p>
469                        Cease all read and write operations.
470                    </p>
471            </li>
472            <li>
473              <p>
474                        Close all open cursors.
475                    </p>
476            </li>
477            <li>
478              <p>
479                        Abort the transaction.
480                    </p>
481            </li>
482            <li>
483              <p>
484                        Optionally retry the operation. If your application
485                        retries deadlocked operations, the new attempt must
486                        be made using a new transaction.
487                    </p>
488            </li>
489          </ol>
490        </div>
491        <div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
492          <h3 class="title">Note</h3>
493          <p>
494                    If a thread has deadlocked, it may not make any
495                    additional database calls using the handle that has
496                    deadlocked.
497                </p>
498        </div>
499        <p>
500                For example:
501            </p>
502        <pre class="programlisting">retry:
503    ret = envp-&gt;txn_begin(envp, NULL, &amp;txn, 0);
504    if (ret != 0) {
505            envp-&gt;err(envp, ret, "txn_begin failed");
506            return (EXIT_FAILURE);
507    }
508    ...
509    /* key and data are Dbts. Their usage is omitted for brevity. */
510    ...
511    switch (ret = dbp-&gt;put(dbp, txn, &amp;key, &amp;data, 0)) {
512        case 0:
513            break;
514        /* Deadlock handling goes here */
515        case DB_LOCK_DEADLOCK:
516            /* Abort the transaction */
517            (void)txn-&gt;abort(txn);
518
519            /* 
520             * retry_count is a counter used to identify how many times
521             * we've retried this operation. To avoid the potential for
522             * endless looping, we won't retry more than 
523             * MAX_DEADLOCK_RETRIES times.
524             */
525            if (retry_count &lt; MAX_DEADLOCK_RETRIES) {
526                printf("Got DB_LOCK_DEADLOCK.\n");
527                printf("Retrying write operation.\n");
528                    retry_count++;
529                    goto retry;
530             }
531             printf("Got DB_LOCK_DEADLOCK and out of retries.");
532             printf("Giving up.\n");
533             return (EXIT_FAILURE);
534         default:
535            /* If some random database error occurs, we just give up */
536            envp-&gt;err(envp, ret, "db put failed");
537            ret = txn-&gt;abort(txn);
538            if (ret != 0) {
539                envp-&gt;err(envp, ret, "txn abort failed");
540                return (EXIT_FAILURE);
541             } 
542         }
543    /* If all goes well, commit the transaction */
544    ret = txn-&gt;commit(txn, 0);
545    if (ret != 0) {
546        envp-&gt;err(envp, ret, "txn commit failed");
547        return (EXIT_FAILURE);
548    }
549
550    return (EXIT_SUCCESS); </pre>
551      </div>
552    </div>
553    <div class="navfooter">
554      <hr />
555      <table width="100%" summary="Navigation footer">
556        <tr>
557          <td width="40%" align="left"><a accesskey="p" href="blocking_deadlocks.html">Prev</a>��</td>
558          <td width="20%" align="center">
559            <a accesskey="u" href="txnconcurrency.html">Up</a>
560          </td>
561          <td width="40%" align="right">��<a accesskey="n" href="isolation.html">Next</a></td>
562        </tr>
563        <tr>
564          <td width="40%" align="left" valign="top">Locks, Blocks, and Deadlocks��</td>
565          <td width="20%" align="center">
566            <a accesskey="h" href="index.html">Home</a>
567          </td>
568          <td width="40%" align="right" valign="top">��Isolation</td>
569        </tr>
570      </table>
571    </div>
572  </body>
573</html>
574