You can configure JE to use degree 1 isolation (see Transactions and Concurrency) by configuring it to perform uncommitted reads. Uncommitted reads allows a reader to see modifications made but not committed by a transaction in which the read is not being performed.
Uncommitted reads can improve your application's performance by avoiding lock contention between the reader and other threads that are writing to the database. However, they are also dangerous because there is a possibility that the data returned as a part of an uncommitted read will disappear as the result of an abort on the part of the transaction who is holding the write lock. This violates the consistency and isolation portion of your ACID protection.
Concurrency and transactions are described in more detail in Transactions and Concurrency.
You can configure the default uncommitted read behavior for a transaction using TransactionConfig.setReadUncommitted():
package je.gettingStarted; import com.sleepycat.je.Database; import com.sleepycat.je.DatabaseEntry; import com.sleepycat.je.Environment; import com.sleepycat.je.LockMode; import com.sleepycat.je.Transaction; import com.sleepycat.je.TransactionConfig; ... Database myDb = null; Environment myEnv = null; Transaction txn = null; try { // Environment and database open omitted ... TransactionConfig tc = new TransactionConfig(); tc.setReadUncommitted(true); // Use read uncommitted isolation txn = myEnv.beginTransaction(null, tc); DatabaseEntry theKey = new DatabaseEntry((new String("theKey")).getBytes("UTF-8")); DatabaseEntry theData = new DatabaseEntry(); myDb.get(txn, theKey, theData, LockMode.DEFAULT); } catch (Exception e) { // Exception handling goes here }
You can also configure the uncommitted read behavior on a read-by-read basis by specifying LockMode.READ_UNCOMMITTED:
package je.gettingStarted; import com.sleepycat.je.Database; import com.sleepycat.je.DatabaseEntry; import com.sleepycat.je.Environment; import com.sleepycat.je.LockMode; import com.sleepycat.je.Transaction; ... Database myDb = null; Environment myEnv = null; Transaction txn = null; try { // Environment and database open omitted ... txn = myEnv.beginTransaction(null, null); DatabaseEntry theKey = new DatabaseEntry((new String("theKey")).getBytes("UTF-8")); DatabaseEntry theData = new DatabaseEntry(); myDb.get(txn, theKey, theData, LockMode.READ_UNCOMMITTED); } catch (Exception e) { // Exception handling goes here }
When using cursors, you can specify the uncommitted read behavior as described above, or you can specify it using CursorConfig.setReadUncommitted():
package je.gettingStarted; import com.sleepycat.je.Cursor; import com.sleepycat.je.CursorConfig; import com.sleepycat.je.Database; import com.sleepycat.je.DatabaseEntry; import com.sleepycat.je.Environment; import com.sleepycat.je.Transaction; import com.sleepycat.je.LockMode; ... Cursor cursor = null; Database myDb = null; Environment myEnv = null; Transaction txn = null; try { // Environment and database open omitted ... DatabaseEntry theKey = new DatabaseEntry((new String("theKey")).getBytes("UTF-8")); DatabaseEntry theData = new DatabaseEntry(); // Start a transaction txn = myEnv.beginTransaction(null, null); // Open a cursor using the transaction CursorConfig cc = new CursorConfig(); cc.setReadUncommitted(true); // Perform uncommitted reads cursor = myDb.openCursor(txn, cc); cursor.getSearchKey(theKey, theData, LockMode.DEFAULT); } catch (Exception e) { // Exception handling goes here }