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