As previously noted, by default transaction commits are durable because they cause the modifications performed under the transaction to be synchronously recorded in your on-disk log files. However, it is possible to use non-durable transactions.
You may want non-durable transactions for performance reasons. For example, you might be using transactions simply for the isolation guarantee. In this case, you might want to relax the synchronized write to disk that JE normally performs as part of a transaction commit. Doing so means that your data will still make it to disk; however, your application will not necessarily have to wait for the disk I/O to complete before it can perform another database operation. This can greatly improve throughput for some workloads.
To relax the durability guarantee for your transactions,
you use the Durability
class to
define the durability policy that you want to use. The
Durability
class constructor takes
three arguments, only one of which is interesting for a
standalone transactional application:
The synchronization policy for the local machine.
The synchronization policy for Replicas. Used only for JE HA applications.
The acknowledgement policy. Again, this is required only for JE HA applications.
We describe JE High Availability Applications in the Berkeley DB, Java Edition Getting Started with High Availability Applications guide.
The synchronization policy that you give the
Durability
class constructor can be
one of the following:
Durability.SyncPolicy.SYNC
Write and synchronously flush the log to disk upon transaction commit. This offers the most durable transaction configuration because the commit operation will not return until all of the disk I/O is complete. But, conversely, this offers the worse possible write performance because disk I/O is an expensive and time-consuming operation.
This is the default synchronization policy. A transaction that uses this policy is considered to be durable.
Durability.SyncPolicy.NO_SYNC
This causes JE to not synchronously force any data to disk upon transaction commit. That is, the modifications are held entirely inside the JVM and the modifications are not forced to the file system for long-term storage. Note, however, that the data will eventually make it to the filesystem (assuming no application or OS crashes) as a part of JE's management of its logging buffers and/or cache.
This form of a commit provides a weak durability guarantee because data loss can occur due to an application, JVM, or OS crash. In fact, this represents the least durable configuration that you can provide for your transactions. But it also offers much better write performance than the other options.
Durability.SyncPolicy.WRITE_NO_SYNC
This causes data to be synchronously written to the OS's file system buffers upon transaction commit. The data will eventually be written to disk, but this occurs when the operating system chooses to schedule the activity; the transaction commit can complete successfully before this disk I/O is performed by the OS.
This form of commit protects you against application and JVM crashes, but not against OS crashes. This method offers less room for the possibility of data loss than does NO_SYNC.
You can specify your durability policy on an
environment-wide basis by creating a
Durability
class and then giving it
to EnvironmentConfig.setDurability()
.
You can also override the environment default durability
policy on a transaction-by-transaction basis by providing a
Durability
class to the
TransactionConfig
object you use to
configure your transaction using the
TransactionConfig.setDurability()
method.
For example:
package je.txn; import com.sleepycat.je.Database; import com.sleepycat.je.DatabaseConfig; import com.sleepycat.je.DatabaseEntry; import com.sleepycat.je.DatabaseException;import com.sleepycat.je.Durability;
import com.sleepycat.je.Environment; import com.sleepycat.je.EnvironmentConfig; import com.sleepycat.je.Transaction;import com.sleepycat.je.TransactionConfig;
import java.io.File; ... Database myDatabase = null; Environment myEnv = null; try {Durability defaultDurability = new Durability(Durability.SyncPolicy.NO_SYNC, null, // unused by non-HA applications. null); // unused by non-HA applications.
EnvironmentConfig myEnvConfig = new EnvironmentConfig(); myEnvConfig.setTransactional(true);myEnvConfig.setDurability(defaultDurability);
myEnv = new Environment(new File("/my/env/home"), myEnvConfig); // Open the database. Create it if it does not already exist. DatabaseConfig dbConfig = new DatabaseConfig(); dbConfig.setTransactional(true); myDatabase = myEnv.openDatabase(null, "sampleDatabase", dbConfig); String keyString = "thekey"; String dataString = "thedata"; DatabaseEntry key = new DatabaseEntry(keyString.getBytes("UTF-8")); DatabaseEntry data = new DatabaseEntry(dataString.getBytes("UTF-8"));Durability newDurability = new Durability(Durability.SyncPolicy.WRITE_NO_SYNC, null, // unused by non-HA applications. null); // unused by non-HA applications. TransactionConfig tc = new TransactionConfig(); tc.setDurability(newDurability); Transaction txn = myEnv.beginTransaction(null, tc);
try { myDatabase.put(txn, key, data); txn.commit(); } catch (Exception e) { if (txn != null) { txn.abort(); txn = null; } } } catch (DatabaseException de) { // Exception handling goes here }