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                            
233                            <span>
234                                specifying <code class="literal">true</code> to 
235
236                                <span>
237                                <code class="methodname">DatabaseConfig.setReadUncommitted()</code>.
238                                (If you are using the DPL, you must
239                                provide this
240                                <code class="classname">DatabaseConfig</code>
241                                object to the entity store using the 
242                                <code class="methodname">EntityStore.setPrimaryConfig()</code>
243                                method.)
244                                </span>
245                            </span>
246                    </p>
247            </li>
248            <li>
249              <p>
250                            
251                            <span>
252                                Specify that you want to use uncommitted reads when you 
253                                create a transaction or open the cursor.
254                                To do this, you use the <code class="methodname">setReadUncommitted()</code>
255                                method on the relevant configuration object
256                                (<code class="classname">TransactionConfig</code> or
257                                <code class="classname">CursorConfig</code>).
258                            </span>
259
260                    </p>
261            </li>
262          </ol>
263        </div>
264        <p>
265                For example, the following opens the database such that it supports uncommitted reads, and then creates a
266                transaction that causes all reads performed within it to use uncommitted reads. Remember that simply opening
267                the database to support uncommitted reads is not enough; you must also declare your read operations to be
268                performed using uncommitted reads. 
269            </p>
270        <pre class="programlisting">package db.txn;
271                                                                                                                                     
272import com.sleepycat.db.Database;
273import com.sleepycat.db.DatabaseConfig;
274import com.sleepycat.db.DatabaseEntry;
275import com.sleepycat.db.DatabaseException;
276import com.sleepycat.db.DatabaseType;
277import com.sleepycat.db.Environment;
278import com.sleepycat.db.EnvironmentConfig;
279import com.sleepycat.db.Transaction;
280import com.sleepycat.db.TransactionConfig;
281
282import java.io.File;
283                                                                                                                                     
284...
285                                                                                                                                     
286Database myDatabase = null;
287Environment myEnv = null;
288try {
289    EnvironmentConfig myEnvConfig = new EnvironmentConfig();
290    myEnvConfig.setTransactional(true);
291    myEnvConfig.setInitializeCache(true);
292    myEnvConfig.setInitializeLocking(true);
293    myEnvConfig.setInitializeLogging(true);
294
295    myEnv = new Environment(new File("/my/env/home"),
296                              myEnvConfig);
297
298    // Open the database.
299    DatabaseConfig dbConfig = new DatabaseConfig();
300    dbConfig.setTransactional(true);
301    dbConfig.setType(DatabaseType.BTREE);
302    dbConfig.setAllowCreate(true);
303    dbConfig.setReadUncommitted(true);      // Enable uncommitted reads.
304    myDatabase = myEnv.openDatabase(null,              // txn handle
305                                    "sampleDatabase",  // db file name
306                                    null,              // db name
307                                    dbConfig);
308    TransactionConfig txnConfig = new TransactionConfig();
309    txnConfig.setReadUncommitted(true);          // Use uncommitted reads 
310                                                 // for this transaction.
311    Transaction txn = myEnv.beginTransaction(null, txnConfig);
312
313    // From here, you perform your database reads and writes as normal,
314    // committing and aborting the transactions as is necessary, and
315    // testing for deadlock exceptions as normal (omitted for brevity). 
316        
317    ...</pre>
318        <p>
319        If you are using the DPL:
320</p>
321        <pre class="programlisting">package persist.txn;
322                                                                                                                                     
323import com.sleepycat.db.DatabaseConfig;
324import com.sleepycat.db.DatabaseEntry;
325import com.sleepycat.db.DatabaseException;
326import com.sleepycat.db.DatabaseType;
327import com.sleepycat.db.Environment;
328import com.sleepycat.db.EnvironmentConfig;
329import com.sleepycat.db.Transaction;
330import com.sleepycat.db.TransactionConfig;
331
332import com.sleepycat.persist.EntityStore;
333import com.sleepycat.persist.StoreConfig;
334
335import java.io.File;
336
337...
338                                                                                                                                     
339EntityStore myStore = null;
340Environment myEnv = null;
341try {
342    EnvironmentConfig myEnvConfig = new EnvironmentConfig();
343    myEnvConfig.setTransactional(true);
344    myEnvConfig.setInitializeCache(true);
345    myEnvConfig.setInitializeLocking(true);
346    myEnvConfig.setInitializeLogging(true);
347
348    myEnv = new Environment(new File("/my/env/home"),
349                              myEnvConfig);
350
351    // Open the store.
352    StoreConfig myStoreConfig = new StoreConfig();
353    myStoreConfig.setAllowCreate(true);
354    myStoreConfig.setTransactional(true);
355
356    // You must set all these fields if you are going to use
357    // a DatabaseConfig object with your new entity store.
358    DatabaseConfig dbConfig = new DatabaseConfig();
359    dbConfig.setTransactional(true);
360    dbConfig.setAllowCreate(true);
361    dbConfig.setType(DatabaseType.BTREE);
362    dbConfig.setReadUncommitted(true);      // Enable uncommitted reads.
363
364    myStore = new EntityStore(myEnv, "store_name", myStoreConfig);
365
366    // Set the DatabaseConfig object, so that the underlying
367    // database is configured for uncommitted reads.
368    myStore.setPrimaryConfig(SomeEntityClass.class, dbConfig);
369
370    TransactionConfig txnConfig = new TransactionConfig();
371    txnConfig.setReadUncommitted(true);          // Use uncommitted reads 
372                                                 // for this transaction.
373    Transaction txn = myEnv.beginTransaction(null, txnConfig);
374
375    // From here, you perform your store reads and writes as normal,
376    // committing and aborting the transactions as is necessary, and
377    // testing for deadlock exceptions as normal (omitted for brevity). 
378        
379    ...</pre>
380        <p>
381        You can also configure uncommitted read isolation on a read-by-read basis
382        by specifying <code class="literal">LockMode.READ_UNCOMMITTED</code>:
383    </p>
384        <pre class="programlisting">package db.txn;
385
386import com.sleepycat.db.Database;
387import com.sleepycat.db.DatabaseEntry;
388import com.sleepycat.db.Environment;
389import com.sleepycat.db.LockMode;
390import com.sleepycat.db.Transaction;
391
392...
393
394Database myDb = null;
395Environment myEnv = null;
396Transaction txn = null;
397
398try {
399
400    // Environment and database open omitted
401
402    ...
403
404    txn = myEnv.beginTransaction(null, null);
405
406    DatabaseEntry theKey =
407        new DatabaseEntry((new String("theKey")).getBytes("UTF-8"));
408    DatabaseEntry theData = new DatabaseEntry();
409
410    myDb.get(txn, theKey, theData, LockMode.READ_UNCOMMITTED);
411} catch (Exception e) {
412    // Exception handling goes here
413} </pre>
414        <p>
415            Using the DPL:
416    </p>
417        <pre class="programlisting">package persist.txn;
418
419import com.sleepycat.db.Environment;
420import com.sleepycat.db.LockMode;
421import com.sleepycat.db.Transaction;
422
423import com.sleepycat.persist.PrimaryIndex;
424...
425
426Environment myEnv = null;
427Transaction txn = null;
428
429try {
430
431    // Environment and database open omitted
432
433    ...
434
435    txn = myEnv.beginTransaction(null, null);
436
437    AnEntityClass aec = aPrimaryIndex.get(txn, "pKeya", 
438                            LockMode.READ_UNCOMMITTED);
439} catch (Exception e) {
440    // Exception handling goes here
441} </pre>
442      </div>
443      <div class="sect2" lang="en" xml:lang="en">
444        <div class="titlepage">
445          <div>
446            <div>
447              <h3 class="title"><a id="readcommitted"></a>Committed Reads</h3>
448            </div>
449          </div>
450        </div>
451        <p>
452                You can configure your transaction so that the data being
453                read by a transactional cursor is consistent so long as it
454                is being addressed by the cursor. However, once the cursor is done reading the 
455                    
456                    
457                    <span>
458                        object or record (that is, reading records from the page that it currently has locked),
459                    </span>
460                the cursor releases its lock on that
461                    
462                    
463                    <span>
464                            object, record or page.
465                    </span>
466                 This means that the data the cursor has read and released
467                 may change before the cursor's transaction has completed.
468              </p>
469        <p>
470                For example,
471                suppose you have two transactions, <code class="literal">Ta</code> and <code class="literal">Tb</code>. Suppose further that
472                <code class="literal">Ta</code> has a cursor that reads <code class="literal">record R</code>, but does not modify it. Normally,
473                <code class="literal">Tb</code> would then be unable to write <code class="literal">record R</code> because
474                <code class="literal">Ta</code> would be holding a read lock on it. But when you configure your transaction for
475                committed reads, <code class="literal">Tb</code> <span class="emphasis"><em>can</em></span> modify <code class="literal">record
476                R</code> before <code class="literal">Ta</code> completes, so long as the reading cursor is no longer
477                addressing the 
478                    
479                    
480                    <span>
481                        object, record or page.
482                    </span>
483             </p>
484        <p>
485                When you configure your application for this level of isolation, you may see better performance
486                throughput because there are fewer read locks being held by your transactions. 
487                Read committed isolation is most useful when you have a cursor that is reading and/or writing records in
488                a single direction, and that does not ever have to go back to re-read those same records. In this case,
489                you can allow DB to release read locks as it goes, rather than hold them for the life of the
490                transaction.
491             </p>
492        <p>
493                To configure your application to use committed reads, do one of the following:
494            </p>
495        <div class="itemizedlist">
496          <ul type="disc">
497            <li>
498              <p>
499                        Create your transaction such that it allows committed reads. You do this by
500                            
501                            <span>
502                                specifying <code class="literal">true</code> to 
503                                <code class="methodname">TransactionConfig.setReadCommitted()</code>.
504                            </span>
505                    </p>
506            </li>
507            <li>
508              <p>
509                            
510                            <span>
511                                Specify <code class="literal">true</code> to 
512                                    <code class="methodname">CursorConfig.setReadCommitted()</code>.
513                            </span>
514                    </p>
515            </li>
516          </ul>
517        </div>
518        <p>
519                For example, the following creates a transaction that allows committed reads:
520            </p>
521        <pre class="programlisting">package db.txn;
522                                                                                                                                     
523import com.sleepycat.db.Database;
524import com.sleepycat.db.DatabaseConfig;
525import com.sleepycat.db.DatabaseEntry;
526import com.sleepycat.db.DatabaseException;
527import com.sleepycat.db.Environment;
528import com.sleepycat.db.EnvironmentConfig;
529import com.sleepycat.db.Transaction;
530import com.sleepycat.db.TransactionConfig;
531
532import java.io.File;
533                                                                                                                                     
534...
535                                                                                                                                     
536Database myDatabase = null;
537Environment myEnv = null;
538try {
539    EnvironmentConfig myEnvConfig = new EnvironmentConfig();
540    myEnvConfig.setTransactional(true);
541    myEnvConfig.setInitializeCache(true);
542    myEnvConfig.setInitializeLocking(true);
543    myEnvConfig.setInitializeLogging(true);
544
545    myEnv = new Environment(new File("/my/env/home"),
546                              myEnvConfig);
547
548    // Open the database.
549    // Notice that we do not have to specify any properties to the 
550    // database to allow committed reads (this is as opposed to 
551    // uncommitted reads where we DO have to specify a property on 
552    // the database open.
553    DatabaseConfig dbConfig = new DatabaseConfig();
554    dbConfig.setTransactional(true);
555    dbConfig.setType(DatabaseType.BTREE);
556
557    myDatabase = myEnv.openDatabase(null,              // txn handle
558                                    "sampleDatabase",  // db file name
559                                    null,              // db name
560                                    dbConfig);
561    String keyString = "thekey";
562    String dataString = "thedata";
563    DatabaseEntry key = 
564        new DatabaseEntry(keyString.getBytes("UTF-8"));
565    DatabaseEntry data = 
566        new DatabaseEntry(dataString.getBytes("UTF-8"));
567
568    TransactionConfig txnConfig = new TransactionConfig();
569
570    // Open the transaction and enable committed reads. All cursors open
571    // with this transaction handle will use read committed isolation.
572    txnConfig.setReadCommitted(true);
573    Transaction txn = myEnv.beginTransaction(null, txnConfig);
574
575    // From here, you perform your database reads and writes as normal,
576    // committing and aborting the transactions as is necessary, and
577    // testing for deadlock exceptions as normal (omitted for brevity). 
578
579    // Using transactional cursors with concurrent applications is 
580    // described in more detail in the following section.
581        
582    ...</pre>
583        <p>
584    Using the DPL:
585</p>
586        <pre class="programlisting">package persist.txn;
587                                                                                                                                     
588import com.sleepycat.db.Environment;
589import com.sleepycat.db.EnvironmentConfig;
590import com.sleepycat.db.Transaction;
591import com.sleepycat.db.TransactionConfig;
592
593import com.sleepycat.persist.EntityStore;
594import com.sleepycat.persist.StoreConfig;
595
596import java.io.File;
597                                                                                                                                     
598...
599                                                                                                                                     
600EntityStore myStore = null;
601Environment myEnv = null;
602try {
603    EnvironmentConfig myEnvConfig = new EnvironmentConfig();
604    myEnvConfig.setTransactional(true);
605    myEnvConfig.setInitializeCache(true);
606    myEnvConfig.setInitializeLocking(true);
607    myEnvConfig.setInitializeLogging(true);
608
609    myEnv = new Environment(new File("/my/env/home"),
610                              myEnvConfig);
611
612    // Instantiate the store.
613    StoreConfig myStoreConfig = new StoreConfig();
614    myStoreConfig.setAllowCreate(true);
615    myStoreConfig.setTransactional(true);
616
617    TransactionConfig txnConfig = new TransactionConfig();
618
619    // Open the transaction and enable committed reads. All cursors open
620    // with this transaction handle will use read committed isolation.
621    txnConfig.setReadCommitted(true);
622    Transaction txn = myEnv.beginTransaction(null, txnConfig);
623
624    // From here, you perform your store reads and writes as normal,
625    // committing and aborting the transactions as is necessary, and
626    // testing for deadlock exceptions as normal (omitted for brevity). 
627
628    // Using transactional cursors with concurrent applications is 
629    // described in more detail in the following section.
630        
631    ...</pre>
632        <p>
633        You can also configure read committed isolation on a read-by-read basis
634        by specifying <code class="literal">LockMode.READ_COMMITTED</code>:
635    </p>
636        <pre class="programlisting">package db.txn;
637
638import com.sleepycat.db.Database;
639import com.sleepycat.db.DatabaseEntry;
640import com.sleepycat.db.Environment;
641import com.sleepycat.db.LockMode;
642import com.sleepycat.db.Transaction;
643
644...
645
646Database myDb = null;
647Environment myEnv = null;
648Transaction txn = null;
649
650try {
651
652    // Environment and database open omitted
653
654    ...
655
656    txn = myEnv.beginTransaction(null, null);
657
658    DatabaseEntry theKey =
659        new DatabaseEntry((new String("theKey")).getBytes("UTF-8"));
660    DatabaseEntry theData = new DatabaseEntry();
661
662    myDb.get(txn, theKey, theData, LockMode.READ_COMMITTED);
663} catch (Exception e) {
664    // Exception handling goes here
665} </pre>
666        <p>
667            Using the DPL:
668    </p>
669        <pre class="programlisting">package persist.txn;
670
671import com.sleepycat.db.Environment;
672import com.sleepycat.db.LockMode;
673import com.sleepycat.db.Transaction;
674
675import com.sleepycat.persist.PrimaryIndex;
676...
677
678Environment myEnv = null;
679Transaction txn = null;
680
681try {
682
683    // Environment and database open omitted
684
685    ...
686
687    txn = myEnv.beginTransaction(null, null);
688
689    // Primary index creation omitted
690    ...
691
692    AnEntityClass aec = aPrimaryIndex.get(txn, "pKeya", 
693                            LockMode.READ_COMMITTED);
694} catch (Exception e) {
695    // Exception handling goes here
696} </pre>
697      </div>
698      <div class="sect2" lang="en" xml:lang="en">
699        <div class="titlepage">
700          <div>
701            <div>
702              <h3 class="title"><a id="snapshot_isolation"></a>Using Snapshot Isolation</h3>
703            </div>
704          </div>
705        </div>
706        <p>
707                    By default DB uses serializable isolation. An
708                    important side effect of this isolation level is that
709                    read operations obtain read locks on database pages,
710                    and then hold those locks until the read operation is
711                    completed. 
712                    
713                    <span>
714                    When you are using transactional cursors, this 
715                    means that read locks are held until the transaction commits or
716                    aborts. In that case, over time a transactional cursor
717                    can gradually block all other transactions from writing
718                    to the database.
719                    </span>
720            </p>
721        <p>
722                    You can avoid this by using snapshot isolation.
723                    Snapshot isolation uses <span class="emphasis"><em>multiversion
724                    concurrency control</em></span> to guarantee
725                    repeatable reads. What this means is that every time a
726                    writer would take a read lock on a page, instead a copy of
727                    the page is made and the writer operates on that page
728                    copy. This frees other writers from blocking due to a
729                    read lock held on the page.
730            </p>
731        <div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
732          <h3 class="title">Note</h3>
733          <p>
734                        Snapshot isolation is strongly recommended for read-only threads when writer
735                        threads are also running, as this will eliminate read-write contention and
736                        greatly improve transaction throughput for your writer threads. However, in
737                        order for snapshot isolation to work for your reader-only threads, you must
738                        of course use transactions for your DB reads.
739                    </p>
740        </div>
741        <div class="sect3" lang="en" xml:lang="en">
742          <div class="titlepage">
743            <div>
744              <div>
745                <h4 class="title"><a id="sisolation_cost"></a>Snapshot Isolation Cost</h4>
746              </div>
747            </div>
748          </div>
749          <p>
750                    Snapshot isolation does not come without a cost.
751                    Because pages are being duplicated before being
752                    operated upon, the cache will fill up faster. This
753                    means that you might need a larger cache in order to
754                    hold the entire working set in memory.
755            </p>
756          <p>
757                    If the cache becomes full of page copies before old
758                    copies can be discarded, additional I/O will occur as
759                    pages are written to temporary "freezer" files on disk.
760                    This can substantially reduce throughput, and should be
761                    avoided if possible by configuring a large cache and
762                    keeping snapshot isolation transactions short.
763            </p>
764          <p>
765                    You can estimate how large your cache should be by
766                    taking a checkpoint, followed by a call to the 
767                    
768                    
769                    <code class="methodname">Environment.getArchiveLogFiles()</code>
770                    method. The amount of cache required is approximately
771                    double the size of the remaining log files (that is,
772                    the log files that cannot be archived).
773            </p>
774        </div>
775        <div class="sect3" lang="en" xml:lang="en">
776          <div class="titlepage">
777            <div>
778              <div>
779                <h4 class="title"><a id="sisolation_maxtxn"></a>Snapshot Isolation Transactional Requirements</h4>
780              </div>
781            </div>
782          </div>
783          <p>
784                    In addition to an increased cache size, you may also
785                    need to increase the maximum number of transactions
786                    that your application supports. (See 
787                    <a class="xref" href="maxtxns.html" title="Configuring the Transaction Subsystem">Configuring the Transaction Subsystem</a>
788                    for details on how to set this.) 
789                    In the worst case scenario, you might need to configure your application for one
790                    more transaction for every page in the cache. This is
791                    because transactions are retained until the last page
792                    they created is evicted from the cache.
793            </p>
794        </div>
795        <div class="sect3" lang="en" xml:lang="en">
796          <div class="titlepage">
797            <div>
798              <div>
799                <h4 class="title"><a id="sisolation_whenuse"></a>When to Use Snapshot Isolation</h4>
800              </div>
801            </div>
802          </div>
803          <p>
804                           Snapshot isolation is best used when all or most
805                           of the following conditions are true:
806                   </p>
807          <div class="itemizedlist">
808            <ul type="disc">
809              <li>
810                <p>
811                                        You can have a large cache relative to your working data set size. 
812                                   </p>
813              </li>
814              <li>
815                <p>
816                                        You require repeatable reads. 
817                                   </p>
818              </li>
819              <li>
820                <p>
821                                        You will be using transactions that routinely work on
822                                        the entire database, or more commonly,
823                                        there is data in your database that will be very
824                                        frequently written by more than one transaction.
825                                   </p>
826              </li>
827              <li>
828                <p>
829                                           Read/write contention is
830                                           limiting your application's
831                                           throughput, or the application
832                                           is all or mostly read-only and
833                                           contention for the lock manager
834                                           mutex is limiting throughput.
835                                   </p>
836              </li>
837            </ul>
838          </div>
839        </div>
840        <div class="sect3" lang="en" xml:lang="en">
841          <div class="titlepage">
842            <div>
843              <div>
844                <h4 class="title"><a id="sisolation_howuse"></a>How to use Snapshot Isolation</h4>
845              </div>
846            </div>
847          </div>
848          <p>
849                           You use snapshot isolation by:
850                   </p>
851          <div class="itemizedlist">
852            <ul type="disc">
853              <li>
854                <p>
855                                           Opening the database <span>or store</span> with
856                                           multiversion support. You can
857                                           configure this either when you
858                                           open your environment or when
859                                           you open your 
860                                           
861                                           
862                                           <span>
863                                                   database or store.
864                                           </span>
865
866                                           <span>
867                                            Use the
868                                           <code class="literal">DB_MULTIVERSION</code>
869                                           flag to configure this support.
870                                            </span>
871
872                                           <span>
873                                            Use the
874                                            <code class="methodname">XmlContainerConfig::setMultiversion()</code>
875                                            option to configure this support when you open your
876                                            container. To configure multiversion support when you
877                                            open your environment, use the
878                                            <code class="literal">DB_MULTIVERSION</code> flag on the
879                                            environment open.
880                                           </span>
881
882                                            <span>
883                                                    Use either the
884                                                    <code class="methodname">EnvironmentConfig.setMultiversion()</code>
885                                                    or the
886                                                    <code class="methodname">DatabaseConfig.setMultiversion()</code>
887                                                    
888                                                    option to configure
889                                                    this support.
890                                            </span>
891                                   </p>
892              </li>
893              <li>
894                <p>
895                                           Configure your <span>cursor or</span>
896                                           transaction to use snapshot isolation.
897                                   </p>
898                <p>
899                                           To do this, 
900                                           
901                                           
902
903                                            <span>
904                                                specify the
905                                                <code class="methodname">TransactionConfig.setSnapshot()</code>
906                                                option when you configure your transaction.
907                                            </span>
908                                   </p>
909              </li>
910            </ul>
911          </div>
912          <p>
913                           The simplest way to take advantage of snapshot
914                           isolation is for queries: keep update
915                           transactions using full read/write locking and
916                           use snapshot isolation on read-only transactions or
917                           cursors. This should minimize blocking of
918                           snapshot isolation transactions and will avoid
919                           deadlock errors.
920                   </p>
921          <p>
922                           If the application has update transactions which
923                           read many items and only update a small set (for
924                           example, scanning until a desired record is
925                           found, then modifying it), throughput may be
926                           improved by running some updates at snapshot
927                           isolation as well.  But doing this means that
928                           you must manage deadlock errors.
929                           See 
930                           <a class="xref" href="lockingsubsystem.html#deadlockresolve" title="Resolving Deadlocks">Resolving Deadlocks</a>
931                           for details.
932                   </p>
933          <p>
934                           The following code fragment turns
935                           on snapshot isolation for a transaction:
936                   </p>
937          <pre class="programlisting">package db.txn;
938
939import com.sleepycat.db.Database;
940import com.sleepycat.db.DatabaseType;
941import com.sleepycat.db.DatabaseConfig;
942import com.sleepycat.db.DatabaseException;
943import com.sleepycat.db.Environment;
944import com.sleepycat.db.EnvironmentConfig;
945
946import java.io.File;
947import java.io.FileNotFoundException;
948
949...
950
951Database myDatabase = null;
952Environment myEnv = null;
953try {
954    EnvironmentConfig myEnvConfig = new EnvironmentConfig();
955    myEnvConfig.setInitializeCache(true);
956    myEnvConfig.setInitializeLocking(true);
957    myEnvConfig.setInitializeLogging(true);
958    myEnvConfig.setTransactional(true);
959    <strong class="userinput"><code>myEnvConfig.setMultiversion(true);</code></strong>
960
961    myEnv = new Environment(new File("/my/env/home"),
962                              myEnvConfig);
963
964    // Open the database.
965    DatabaseConfig dbConfig = new DatabaseConfig();
966    dbConfig.setTransactional(true);
967    dbConfig.setType(DatabaseType.BTREE);
968    myDatabase = myEnv.openDatabase(null,               // txn handle
969                                    "sampleDatabase",   // db file name
970                                    null,             // db name
971                                    dbConfig);
972
973...
974
975    <strong class="userinput"><code>TransactionConfig txnConfig = new TransactionConfig();
976    txnConfig.setSnapshot(true);</code></strong>
977    txn = myEnv.beginTransaction(null, <strong class="userinput"><code>txnConfig</code></strong>);
978
979...
980
981} catch (DatabaseException de) {
982    // Exception handling goes here
983} catch (FileNotFoundException fnfe) {
984    // Exception handling goes here
985}</pre>
986          <p>
987        When using the DPL:
988</p>
989          <pre class="programlisting">package persist.txn;
990
991import com.sleepycat.db.DatabaseException;
992import com.sleepycat.db.Environment;
993import com.sleepycat.db.EnvironmentConfig;
994
995import com.sleepycat.persist.EntityStore;
996import com.sleepycat.persist.StoreConfig;
997
998import java.io.File;
999import java.io.FileNotFoundException;
1000
1001...
1002
1003EntityStore myStore = null;
1004Environment myEnv = null;
1005try {
1006    EnvironmentConfig myEnvConfig = new EnvironmentConfig();
1007    myEnvConfig.setInitializeCache(true);
1008    myEnvConfig.setInitializeLocking(true);
1009    myEnvConfig.setInitializeLogging(true);
1010    myEnvConfig.setTransactional(true);
1011    <strong class="userinput"><code>myEnvConfig.setMultiversion(true);</code></strong>
1012
1013    myEnv = new Environment(new File("/my/env/home"),
1014                              myEnvConfig);
1015
1016    // Instantiate the store
1017    StoreConfig myStoreConfig = new StoreConfig();
1018    myStoreConfig.setAllowCreate(true);
1019    myStoreConfig.setTransactional(true);
1020
1021    myStore = new EntityStore(myEnv, storeName, myStoreConfig);
1022
1023...
1024
1025    <strong class="userinput"><code>TransactionConfig txnConfig = new TransactionConfig();
1026    txnConfig.setSnapshot(true);</code></strong>
1027    txn = myEnv.beginTransaction(null, <strong class="userinput"><code>txnConfig</code></strong>);
1028
1029...
1030
1031} catch (DatabaseException de) {
1032    // Exception handling goes here
1033} catch (FileNotFoundException fnfe) {
1034    // Exception handling goes here
1035}</pre>
1036        </div>
1037      </div>
1038    </div>
1039    <div class="navfooter">
1040      <hr />
1041      <table width="100%" summary="Navigation footer">
1042        <tr>
1043          <td width="40%" align="left"><a accesskey="p" href="lockingsubsystem.html">Prev</a> </td>
1044          <td width="20%" align="center">
1045            <a accesskey="u" href="txnconcurrency.html">Up</a>
1046          </td>
1047          <td width="40%" align="right"> <a accesskey="n" href="txn_ccursor.html">Next</a></td>
1048        </tr>
1049        <tr>
1050          <td width="40%" align="left" valign="top">The Locking Subsystem </td>
1051          <td width="20%" align="center">
1052            <a accesskey="h" href="index.html">Home</a>
1053          </td>
1054          <td width="40%" align="right" valign="top"> Transactional Cursors and Concurrent Applications</td>
1055        </tr>
1056      </table>
1057    </div>
1058  </body>
1059</html>
1060