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>Isolation</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="lockingsubsystem.html" title="The Locking Subsystem" />
12    <link rel="next" href="txn_ccursor.html" title="Transactional Cursors and Concurrent Applications" />
13  </head>
14  <body>
15    <div class="navheader">
16      <table width="100%" summary="Navigation header">
17        <tr>
18          <th colspan="3" align="center">Isolation</th>
19        </tr>
20        <tr>
21          <td width="20%" align="left"><a accesskey="p" href="lockingsubsystem.html">Prev</a> </td>
22          <th width="60%" align="center">Chapter 4. Concurrency</th>
23          <td width="20%" align="right"> <a accesskey="n" href="txn_ccursor.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="isolation"></a>Isolation</h2>
33          </div>
34        </div>
35        <div></div>
36      </div>
37      <p>
38            Isolation guarantees are an important aspect of transactional
39            protection.  Transactions
40            ensure the data your transaction is working with will not be changed by some other transaction.
41            Moreover, the modifications made by a transaction will never be viewable outside of that transaction until
42            the changes have been committed.
43        </p>
44      <p>
45            That said, there are different degrees of isolation, and you can choose to relax your isolation
46            guarantees to one degree or another depending on your application's requirements. The primary reason why
47            you might want to do this is because of performance; the more isolation you ask your transactions to
48            provide, the more locking that your application must do. With more locking comes a greater chance of
49            blocking, which in turn causes your threads to pause while waiting for a lock. Therefore, by relaxing
50            your isolation guarantees, you can <span class="emphasis"><em>potentially</em></span> improve your application's throughput.
51            Whether you actually see any improvement depends, of course, on
52            the nature of your application's data and transactions.
53        </p>
54      <div class="sect2" lang="en" xml:lang="en">
55        <div class="titlepage">
56          <div>
57            <div>
58              <h3 class="title"><a id="degreesofisolation"></a>Supported Degrees of Isolation</h3>
59            </div>
60          </div>
61          <div></div>
62        </div>
63        <p>
64                DB supports the following levels of isolation:
65            </p>
66        <div class="informaltable">
67          <table border="1" width="80%">
68            <colgroup>
69              <col />
70              <col />
71              <col />
72            </colgroup>
73            <thead>
74              <tr>
75                <th>Degree</th>
76                <th>ANSI Term</th>
77                <th>Definition</th>
78              </tr>
79            </thead>
80            <tbody>
81              <tr>
82                <td>1</td>
83                <td>READ UNCOMMITTED</td>
84                <td>
85                    Uncommitted reads means that one transaction will never
86                    overwrite another transaction's dirty data.  Dirty data is
87                    data that a transaction has modified but not yet committed
88                    to the underlying data store. However, uncommitted reads allows a 
89                    transaction to see data dirtied by another
90                    transaction. In addition, a transaction may read data
91                    dirtied by another transaction, but which subsequently
92                    is aborted by that other transaction. In this latter
93                    case, the reading transaction may be reading data that
94                    never really existed in the database.
95                </td>
96              </tr>
97              <tr>
98                <td>2</td>
99                <td>READ COMMITTED</td>
100                <td>
101                  <p>
102                    Committed read isolation means that degree 1 is observed, except that dirty data is never read. 
103                    </p>
104                  <p>
105                    In addition, this isolation level guarantees that data will never change so long as
106                    it is addressed by the cursor, but the data may change before the reading cursor is closed.
107                    In the case of a transaction, data at the current
108                    cursor position will not change, but once the cursor
109                    moves, the previous referenced data can change. This
110                    means that readers release read locks before the cursor
111                    is closed, and therefore, before the transaction
112                    completes. Note that this level of isolation causes the
113                    cursor to operate in exactly the same way as it does in
114                    the absence of a transaction.
115                    </p>
116                </td>
117              </tr>
118              <tr>
119                <td>3</td>
120                <td>SERIALIZABLE</td>
121                <td>
122                  <p>
123                    Committed read is observed, plus the data read by a transaction, T,  
124                    will never be dirtied by another transaction before T completes.
125                    This means that both read and write locks are not
126                    released until the transaction completes.
127                    </p>
128                  <p>
129                        <span>
130                        In addition, 
131                        </span>
132
133                        
134                        
135                        no transactions will see phantoms.  Phantoms are records 
136                        returned as a result of a search, but which were not seen by 
137                        the same transaction when the identical
138                        search criteria was previously used.
139                    </p>
140                  <p>
141                        This is DB's default isolation guarantee.
142                    </p>
143                </td>
144              </tr>
145            </tbody>
146          </table>
147        </div>
148        <p>
149
150    By default, DB transactions and transactional cursors offer 
151    <span>
152        serializable isolation. 
153    </span>
154    
155    
156    You can optionally reduce your isolation level by configuring DB to use
157    uncommitted read isolation. See 
158        <a href="isolation.html#dirtyreads">Reading Uncommitted Data</a> 
159     for more information.
160
161        You can also configure DB to use committed read isolation. See
162            <a href="isolation.html#readcommitted">Committed Reads</a>
163        for more information.
164        
165  </p>
166        <p>
167          Finally, in addition to DB's normal degrees of isolation, you
168          can also use <span class="emphasis"><em>snapshot isolation</em></span>. This allows
169          you to avoid the read locks that serializable isolation requires. See
170          <a href="isolation.html#snapshot_isolation">Using Snapshot Isolation</a>
171          for details.
172  </p>
173      </div>
174      <div class="sect2" lang="en" xml:lang="en">
175        <div class="titlepage">
176          <div>
177            <div>
178              <h3 class="title"><a id="dirtyreads"></a>Reading Uncommitted Data</h3>
179            </div>
180          </div>
181          <div></div>
182        </div>
183        <p>
184                You can configure your application to read data that has been modified but not yet
185                committed by another transaction; that is, dirty data.  When you do this, you 
186                may see a performance benefit by allowing your
187                application to not have to block waiting for write locks. On the other hand, the data that your
188                application is reading may change before the transaction has completed.
189            </p>
190        <p>
191                When used with transactions, uncommitted reads means that one transaction can see data
192                modified but not yet committed by another transaction. When
193                used with transactional cursors, uncommitted reads means
194                that any database reader can see data modified by the
195                cursor before the cursor's transaction has committed.
196            </p>
197        <p>
198                Because of this, uncommitted reads allow a transaction to read data
199                that may subsequently be aborted by another transaction. In
200                this case, the reading transaction will have read data that
201                never really existed in the database.
202            </p>
203        <p>
204                To configure your application to read uncommitted data:
205            </p>
206        <div class="orderedlist">
207          <ol type="1">
208            <li>
209              <p>
210                        Open your database such that it will allow uncommitted reads. You do this by
211                            <span>
212                                specifying <tt class="literal">DB_READ_UNCOMMITTED</tt> when you open your database.
213                            </span>
214                            
215                    </p>
216            </li>
217            <li>
218              <p>
219                            <span>
220                                Specify <tt class="literal">DB_READ_UNCOMMITTED</tt>
221                                when you create the transaction, 
222                                    <span>
223                                        open the cursor, or read a record from the database.
224                                    </span>
225                                    
226                            </span>
227                            
228
229                    </p>
230            </li>
231          </ol>
232        </div>
233        <p>
234                For example, the following opens the database such that it supports uncommitted reads, and then creates a
235                transaction that causes all reads performed within it to use uncommitted reads. Remember that simply opening
236                the database to support uncommitted reads is not enough; you must also declare your read operations to be
237                performed using uncommitted reads. 
238            </p>
239        <pre class="programlisting">#include &lt;stdio.h&gt;
240#include &lt;stdlib.h&gt;
241
242#include "db.h"
243
244int
245main(void)
246{
247    int ret, ret_c;
248    u_int32_t db_flags, env_flags;
249    DB *dbp;
250    DB_ENV *envp;
251    DB_TXN *txn;
252    const char *db_home_dir = "/tmp/myEnvironment";
253    const char *file_name = "mydb.db";
254    const char *keystr ="thekey";
255    const char *datastr = "thedata";
256    
257    dbp = NULL;
258    envp = NULL;
259
260    /* Open the environment */
261    ret = db_env_create(&amp;envp, 0);
262    if (ret != 0) {
263        fprintf(stderr, "Error creating environment handle: %s\n",
264            db_strerror(ret));
265        return (EXIT_FAILURE);
266    }
267                                                                                                                                  
268    env_flags = DB_CREATE     |  /* If the environment does not
269                                  * exist, create it. */
270                DB_INIT_LOCK  |  /* Initialize locking */
271                DB_INIT_LOG   |  /* Initialize logging */
272                DB_INIT_MPOOL |  /* Initialize the cache */
273                DB_THREAD     |  /* Free-thread the env handle. */
274                DB_INIT_TXN;     /* Initialize transactions */
275
276    ret = envp-&gt;open(envp, db_home_dir, env_flags, 0);
277    if (ret != 0) {
278        fprintf(stderr, "Error opening environment: %s\n",
279            db_strerror(ret));
280        goto err;
281    }
282
283    /* Initialize the DB handle */
284    ret = db_create(&amp;dbp, envp, 0);
285    if (ret != 0) {
286        envp-&gt;err(envp, ret, "Database creation failed");
287        goto err;
288    }
289
290    db_flags = DB_CREATE |             /* Create the db if it does not 
291                                        * exist */
292               DB_AUTO_COMMIT |        /* Enable auto commit */
293               DB_READ_UNCOMMITTED;    /* Enable uncommitted reads */
294
295    ret = dbp-&gt;open(dbp,        /* Pointer to the database */
296                    NULL,       /* Txn pointer */
297                    file_name,  /* File name */
298                    NULL,       /* Logical db name */
299                    DB_BTREE,   /* Database type (using btree) */
300                    db_flags,   /* Open flags */
301                    0);         /* File mode. Using defaults */
302    if (ret != 0) {
303        envp-&gt;err(envp, ret, "Database '%s' open failed",
304            file_name);
305        goto err;
306    }
307
308    /* Get the txn handle */
309    txn = NULL;
310    ret = envp-&gt;txn_begin(envp, NULL, &amp;txn, DB_READ_UNCOMMITTED);
311    if (ret != 0) {
312        envp-&gt;err(envp, ret, "Transaction begin failed.");
313        goto err;
314    }
315
316    /*
317     * From here, you perform your database reads and writes as normal,
318     * committing and aborting the transactions as is necessary, and 
319     * testing for deadlock exceptions as normal (omitted for brevity). 
320     */
321
322     ...  </pre>
323      </div>
324      <div class="sect2" lang="en" xml:lang="en">
325        <div class="titlepage">
326          <div>
327            <div>
328              <h3 class="title"><a id="readcommitted"></a>Committed Reads</h3>
329            </div>
330          </div>
331          <div></div>
332        </div>
333        <p>
334                You can configure your transaction so that the data being
335                read by a transactional cursor is consistent so long as it
336                is being addressed by the cursor. However, once the cursor is done reading the 
337                    
338                    <span>
339                        record (that is, reading records from the page that it currently has locked),
340                    </span>
341                    
342                the cursor releases its lock on that
343                    
344                    <span>
345                        record or page.
346                    </span>
347                    
348                 This means that the data the cursor has read and released
349                 may change before the cursor's transaction has completed.
350              </p>
351        <p>
352                For example,
353                suppose you have two transactions, <tt class="literal">Ta</tt> and <tt class="literal">Tb</tt>. Suppose further that
354                <tt class="literal">Ta</tt> has a cursor that reads <tt class="literal">record R</tt>, but does not modify it. Normally,
355                <tt class="literal">Tb</tt> would then be unable to write <tt class="literal">record R</tt> because
356                <tt class="literal">Ta</tt> would be holding a read lock on it. But when you configure your transaction for
357                committed reads, <tt class="literal">Tb</tt> <span class="emphasis"><em>can</em></span> modify <tt class="literal">record
358                R</tt> before <tt class="literal">Ta</tt> completes, so long as the reading cursor is no longer
359                addressing the 
360                    
361                    <span>
362                        record or page.
363                    </span>
364                    
365             </p>
366        <p>
367                When you configure your application for this level of isolation, you may see better performance
368                throughput because there are fewer read locks being held by your transactions. 
369                Read committed isolation is most useful when you have a cursor that is reading and/or writing records in
370                a single direction, and that does not ever have to go back to re-read those same records. In this case,
371                you can allow DB to release read locks as it goes, rather than hold them for the life of the
372                transaction.
373             </p>
374        <p>
375                To configure your application to use committed reads, do one of the following:
376            </p>
377        <div class="itemizedlist">
378          <ul type="disc">
379            <li>
380              <p>
381                        Create your transaction such that it allows committed reads. You do this by
382                            <span>
383                                specifying <tt class="literal">DB_READ_COMMITTED</tt> when you open the transaction.
384                            </span>
385                            
386                    </p>
387            </li>
388            <li>
389              <p>
390                            <span>
391                                Specify <tt class="literal">DB_READ_COMMITTED</tt>
392                                when you open the cursor. 
393                            </span>
394                            
395                    </p>
396            </li>
397          </ul>
398        </div>
399        <p>
400                For example, the following creates a transaction that allows committed reads:
401            </p>
402        <pre class="programlisting">#include &lt;stdio.h&gt;
403#include &lt;stdlib.h&gt;
404
405#include "db.h"
406
407int
408main(void)
409{
410    int ret, ret_c;
411    u_int32_t db_flags, env_flags;
412    DB *dbp;
413    DB_ENV *envp;
414    DB_TXN *txn;
415    const char *db_home_dir = "/tmp/myEnvironment";
416    const char *file_name = "mydb.db";
417    
418    dbp = NULL;
419    envp = NULL;
420
421    /* Open the environment */
422    ret = db_env_create(&amp;envp, 0);
423    if (ret != 0) {
424        fprintf(stderr, "Error creating environment handle: %s\n",
425            db_strerror(ret));
426        return (EXIT_FAILURE);
427    }
428                                                                                                                                  
429    env_flags = DB_CREATE     |  /* If the environment does not
430                                  * exist, create it. */
431                DB_INIT_LOCK  |  /* Initialize locking */
432                DB_INIT_LOG   |  /* Initialize logging */
433                DB_INIT_MPOOL |  /* Initialize the cache */
434                DB_THREAD     |  /* Free-thread the env handle. */
435                DB_INIT_TXN;     /* Initialize transactions */
436
437    ret = envp-&gt;open(envp, db_home_dir, env_flags, 0);
438    if (ret != 0) {
439        fprintf(stderr, "Error opening environment: %s\n",
440            db_strerror(ret));
441        goto err;
442    }
443
444    /* Initialize the DB handle */
445    ret = db_create(&amp;dbp, envp, 0);
446    if (ret != 0) {
447        envp-&gt;err(envp, ret, "Database creation failed");
448        goto err;
449    }
450
451    /*
452     * Notice that we do not have to specify any flags to the database to
453     * allow committed reads (this is as opposed to uncommitted reads
454     * where we DO have to specify a flag on the database open.
455     */
456    db_flags = DB_CREATE | DB_AUTO_COMMIT;
457    ret = dbp-&gt;open(dbp,        /* Pointer to the database */
458                    NULL,       /* Txn pointer */
459                    file_name,  /* File name */
460                    NULL,       /* Logical db name */
461                    DB_BTREE,   /* Database type (using btree) */
462                    db_flags,   /* Open flags */
463                    0);         /* File mode. Using defaults */
464    if (ret != 0) {
465        envp-&gt;err(envp, ret, "Database '%s' open failed",
466            file_name);
467        goto err;
468    }
469
470    /* Get the txn handle */
471    txn = NULL;
472    /*
473     * Open the transaction and enable committed reads. All cursors open
474     * with this transaction handle will use read committed isolation.
475     */
476    ret = envp-&gt;txn_begin(envp, NULL, &amp;txn, DB_READ_COMMITTED);
477    if (ret != 0) {
478        envp-&gt;err(envp, ret, "Transaction begin failed.");
479        goto err;
480    }
481
482    /*
483     * From here, you perform your database reads and writes as normal,
484     * committing and aborting the transactions as is necessary, and 
485     * testing for deadlock exceptions as normal (omitted for brevity). 
486     *
487     * Using transactional cursors with concurrent applications is 
488     * described in more detail in the following section.
489     */
490
491     ...  </pre>
492      </div>
493      <div class="sect2" lang="en" xml:lang="en">
494        <div class="titlepage">
495          <div>
496            <div>
497              <h3 class="title"><a id="snapshot_isolation"></a>Using Snapshot Isolation</h3>
498            </div>
499          </div>
500          <div></div>
501        </div>
502        <p>
503                    By default DB uses serializable isolation. An
504                    important side effect of this isolation level is that
505                    read operations obtain read locks on database pages,
506                    and then hold those locks until the read operation is
507                    completed. 
508                    
509                    <span>
510                    When you are using transactional cursors, this 
511                    means that read locks are held until the transaction commits or
512                    aborts. In that case, over time a transactional cursor
513                    can gradually block all other transactions from writing
514                    to the database.
515                    </span>
516            </p>
517        <p>
518                    You can avoid this by using snapshot isolation.
519                    Snapshot isolation uses <span class="emphasis"><em>multiversion
520                    concurrency control</em></span> to guarantee
521                    repeatable reads. What this means is that every time a
522                    writer would take a read lock on a page, instead a copy of
523                    the page is made and the writer operates on that page
524                    copy. This frees other writers from blocking due to a
525                    read lock held on the page.
526            </p>
527        <div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
528          <h3 class="title">Note</h3>
529          <p>
530                        Snapshot isolation is strongly recommended for read-only threads when writer
531                        threads are also running, as this will eliminate read-write contention and
532                        greatly improve transaction throughput for your writer threads. However, in
533                        order for snapshot isolation to work for your reader-only threads, you must
534                        of course use transactions for your DB reads.
535                    </p>
536        </div>
537        <div class="sect3" lang="en" xml:lang="en">
538          <div class="titlepage">
539            <div>
540              <div>
541                <h4 class="title"><a id="sisolation_cost"></a>Snapshot Isolation Cost</h4>
542              </div>
543            </div>
544            <div></div>
545          </div>
546          <p>
547                    Snapshot isolation does not come without a cost.
548                    Because pages are being duplicated before being
549                    operated upon, the cache will fill up faster. This
550                    means that you might need a larger cache in order to
551                    hold the entire working set in memory.
552            </p>
553          <p>
554                    If the cache becomes full of page copies before old
555                    copies can be discarded, additional I/O will occur as
556                    pages are written to temporary "freezer" files on disk.
557                    This can substantially reduce throughput, and should be
558                    avoided if possible by configuring a large cache and
559                    keeping snapshot isolation transactions short.
560            </p>
561          <p>
562                    You can estimate how large your cache should be by
563                    taking a checkpoint, followed by a call to the 
564                    <tt class="methodname">DB_ENV-&gt;log_archive()</tt>
565                    
566                    
567                    method. The amount of cache required is approximately
568                    double the size of the remaining log files (that is,
569                    the log files that cannot be archived).
570            </p>
571        </div>
572        <div class="sect3" lang="en" xml:lang="en">
573          <div class="titlepage">
574            <div>
575              <div>
576                <h4 class="title"><a id="sisolation_maxtxn"></a>Snapshot Isolation Transactional Requirements</h4>
577              </div>
578            </div>
579            <div></div>
580          </div>
581          <p>
582                    In addition to an increased cache size, you may also
583                    need to increase the maximum number of transactions
584                    that your application supports. (See 
585                    <a href="maxtxns.html">Configuring the Transaction Subsystem</a>
586                    for details on how to set this.) 
587                    In the worst case scenario, you might need to configure your application for one
588                    more transaction for every page in the cache. This is
589                    because transactions are retained until the last page
590                    they created is evicted from the cache.
591            </p>
592        </div>
593        <div class="sect3" lang="en" xml:lang="en">
594          <div class="titlepage">
595            <div>
596              <div>
597                <h4 class="title"><a id="sisolation_whenuse"></a>When to Use Snapshot Isolation</h4>
598              </div>
599            </div>
600            <div></div>
601          </div>
602          <p>
603                           Snapshot isolation is best used when all or most
604                           of the following conditions are true:
605                   </p>
606          <div class="itemizedlist">
607            <ul type="disc">
608              <li>
609                <p>
610                                        You can have a large cache relative to your working data set size. 
611                                   </p>
612              </li>
613              <li>
614                <p>
615                                        You require repeatable reads. 
616                                   </p>
617              </li>
618              <li>
619                <p>
620                                        You will be using transactions that routinely work on
621                                        the entire database, or more commonly,
622                                        there is data in your database that will be very
623                                        frequently written by more than one transaction.
624                                   </p>
625              </li>
626              <li>
627                <p>
628                                           Read/write contention is
629                                           limiting your application's
630                                           throughput, or the application
631                                           is all or mostly read-only and
632                                           contention for the lock manager
633                                           mutex is limiting throughput.
634                                   </p>
635              </li>
636            </ul>
637          </div>
638        </div>
639        <div class="sect3" lang="en" xml:lang="en">
640          <div class="titlepage">
641            <div>
642              <div>
643                <h4 class="title"><a id="sisolation_howuse"></a>How to use Snapshot Isolation</h4>
644              </div>
645            </div>
646            <div></div>
647          </div>
648          <p>
649                           You use snapshot isolation by:
650                   </p>
651          <div class="itemizedlist">
652            <ul type="disc">
653              <li>
654                <p>
655                                           Opening the database  with
656                                           multiversion support. You can
657                                           configure this either when you
658                                           open your environment or when
659                                           you open your 
660                                           
661                                           <span>
662                                           database.
663                                           </span>
664                                           
665
666                                           <span>
667                                            Use the
668                                           <tt class="literal">DB_MULTIVERSION</tt>
669                                           flag to configure this support.
670                                            </span>
671
672                                            
673                                   </p>
674              </li>
675              <li>
676                <p>
677                                           Configure your <span>cursor or</span>
678                                           transaction to use snapshot isolation.
679                                   </p>
680                <p>
681                                           To do this, 
682                                           
683                                           <span>
684                                                pass the <tt class="literal">DB_TXN_SNAPSHOT</tt> flag 
685                                                when you 
686
687                                                <span>
688                                                  open the cursor or
689                                                </span>
690
691                                                create the transaction. 
692                                            
693                                                <span>
694                                                    If configured for the transaction,
695                                                     then this flag is not required
696                                                     when the cursor is opened.
697                                                </span>
698
699                                            </span>
700
701                                            
702                                   </p>
703              </li>
704            </ul>
705          </div>
706          <p>
707                           The simplest way to take advantage of snapshot
708                           isolation is for queries: keep update
709                           transactions using full read/write locking and
710                           use snapshot isolation on read-only transactions or
711                           cursors. This should minimize blocking of
712                           snapshot isolation transactions and will avoid
713                           deadlock errors.
714                   </p>
715          <p>
716                           If the application has update transactions which
717                           read many items and only update a small set (for
718                           example, scanning until a desired record is
719                           found, then modifying it), throughput may be
720                           improved by running some updates at snapshot
721                           isolation as well.  But doing this means that
722                           you must manage deadlock errors.
723                           See 
724                           <a href="lockingsubsystem.html#deadlockresolve">Resolving Deadlocks</a>
725                           for details.
726                   </p>
727          <p>
728                           The following code fragment turns
729                           on snapshot isolation for a transaction:
730                   </p>
731          <pre class="programlisting">#include &lt;stdio.h&gt;
732#include &lt;stdlib.h&gt;
733
734#include "db.h"
735
736int
737main(void)
738{
739    int ret, ret_c;
740    u_int32_t db_flags, env_flags;
741    DB *dbp;
742    DB_ENV *envp;
743    const char *db_home_dir = "/tmp/myEnvironment";
744    const char *file_name = "mydb.db";
745    
746    dbp = NULL;
747    envp = NULL;
748
749    /* Open the environment */
750    ret = db_env_create(&amp;envp, 0);
751    if (ret != 0) {
752        fprintf(stderr, "Error creating environment handle: %s\n",
753            db_strerror(ret));
754        return (EXIT_FAILURE);
755    }
756                                                                                                                                  
757    env_flags = DB_CREATE |    /* Create the environment if it does 
758                                * not already exist. */
759                DB_INIT_TXN  | /* Initialize transactions */
760                DB_INIT_LOCK | /* Initialize locking. */
761                DB_INIT_LOG  | /* Initialize logging */
762                DB_INIT_MPOOL| /* Initialize the in-memory cache. */
763                <b class="userinput"><tt>DB_MULTIVERSION; /* Support snapshot isolation */</tt></b>
764
765    ret = envp-&gt;open(envp, db_home_dir, env_flags, 0);
766    if (ret != 0) {
767        fprintf(stderr, "Error opening environment: %s\n",
768            db_strerror(ret));
769        goto err;
770    }
771
772    /* Initialize the DB handle */
773    ret = db_create(&amp;dbp, envp, 0);
774    if (ret != 0) {
775        envp-&gt;err(envp, ret, "Database creation failed");
776        goto err;
777    }
778
779    /* 
780     * Nothing needs to be supplied here to support snapshot isolation. 
781     * The environment does, so its databases will too.
782     */
783    db_flags = DB_CREATE | DB_AUTO_COMMIT;
784    ret = dbp-&gt;open(dbp,        /* Pointer to the database */
785                    NULL,       /* Txn pointer */
786                    file_name,  /* File name */
787                    NULL,       /* Logical db name */
788                    DB_BTREE,   /* Database type (using btree) */
789                    db_flags,   /* Open flags */
790                    0);         /* File mode. Using defaults */
791    if (ret != 0) {
792        envp-&gt;err(envp, ret, "Database '%s' open failed",
793            file_name);
794        goto err;
795    }
796
797
798    ....
799
800    ret = envp-&gt;txn_begin(envp, NULL, &amp;txn, <b class="userinput"><tt>DB_TXN_SNAPSHOT</tt></b>);
801
802    /* remainder of the program omitted for brevity */
803
804 </pre>
805        </div>
806      </div>
807    </div>
808    <div class="navfooter">
809      <hr />
810      <table width="100%" summary="Navigation footer">
811        <tr>
812          <td width="40%" align="left"><a accesskey="p" href="lockingsubsystem.html">Prev</a> </td>
813          <td width="20%" align="center">
814            <a accesskey="u" href="txnconcurrency.html">Up</a>
815          </td>
816          <td width="40%" align="right"> <a accesskey="n" href="txn_ccursor.html">Next</a></td>
817        </tr>
818        <tr>
819          <td width="40%" align="left" valign="top">The Locking Subsystem </td>
820          <td width="20%" align="center">
821            <a accesskey="h" href="index.html">Home</a>
822          </td>
823          <td width="40%" align="right" valign="top"> Transactional Cursors and Concurrent Applications</td>
824        </tr>
825      </table>
826    </div>
827  </body>
828</html>
829