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