Committing and Aborting Transactions
Prev | Chapter 7. Transactions | Next

## Committing and Aborting Transactions

When you have completed all database operations that you want to perform from within a transaction, you must commit the transaction. Committing the transaction causes the database modifications to be permanently written to the database. In most cases, committing the transaction also causes the database modifications to be flushed to stable storage.

Once a transaction has been committed, you can no longer use that same transaction handle for subsequent database operations.

Use one of the following methods to commit a transaction:

- `Transaction.commit()`

  Ends the transaction and writes the modifications to your database(s). The database changes may or may not be flushed to stable storage depending on the transaction commit behavior configured for your environment. By default, the changes are flushed to stable storage. This behavior is configurable using `EnvironmentMutableConfig.setTxnNoSync()` or `EnvironmentMutableConfig.setTxnWriteNoSync()`.

- `Transaction.commitSync()`

  Ends the transaction and writes the modifications to your database(s). The database modifications are flushed to stable storage. That is, the modifications are immediately written to the OS's file system buffers and then `fsync()` is called to cause the contents of those buffers to be immediately written to disk. This form of commit provides the strongest possible durability guarantee, but it does so at the expense of higher I/O costs than is incurred by other forms of commit.

- `Transaction.commitWriteNoSync()`

  Ends the transaction and writes the modifications to your database(s). In this case, the modifications are written to the OS's file system buffers so that they will eventually be written to disk. This protects your data against JVM crashes, but not OS crashes.

  This method is faster than `Transaction.commitSync()`, but also more dangerous. Use of this method might mean losing the durability aspect of the transactional subsystem, because a system crash could cause the loss of any modifications held only in memory.

- `Transaction.commitNoSync()`

  Ends the transaction but does not write the modifications. That is, the modifications are held entirely inside the JVM and no attempt is made to pass the modifications to the file system for long-term storage. This form of a commit provides the weakest durability guarantee as data loss can occur due to either a JVM or OS crash.

### Aborting Transactions

If for some reason you do not want to commit a transaction, then call `Transaction.abort()`. Aborting the transaction causes JE to discard all modifications made to the database during the course of the transaction.

Most frequently you will want to call `Transaction.abort()` as a part of your exception handling activity. The circumstances that require you to call `Transaction.abort()` will vary depending on your application's activities. Certainly any time your application catches a `DatabaseException`, the transaction should probably be aborted.

Note that any time your application receives a `DeadlockException`, you must close any cursors opened for the transaction, abort the transaction and, optionally, start over again. For more information, see Transactions and Deadlocks.

For example:

    package je.gettingStarted;

    import com.sleepycat.je.Database;
    import com.sleepycat.je.DatabaseException;
    import com.sleepycat.je.Environment;
    import com.sleepycat.je.Transaction;

    ...

    Database myDb = null;
    Environment myEnv = null;
    Transaction txn = null;

    try {
        // Environment open omitted ...
        txn = myEnv.beginTransaction(null, null);
        myDb = myEnv.openDatabase(txn, "myDbName", null);
        txn.commit();
    } catch (DatabaseException dbe) {
        if (txn != null) {
            try {
                txn.abort();
            } catch (DatabaseException txnError) {
                // Error reporting goes here
            }
        }
    }

### Using Autocommit

If your application does not require atomicity for multiple database operations, then you can use JE's autocommit feature to transactionally protect your database operations. Essentially, autocommit is a convenience feature that causes JE to automatically use a transaction for those write operations that do not provide a transaction handle.

### Note

Autocommit cannot be used when performing write operations using a cursor.

To use autocommit:

1. Open your environment and database such that they support transactions. See Enabling and Starting Transactions for a description of how to do this.

2. Do not provide a transaction handle for the database put or delete operation. Instead, simply specify `null` for the transaction parameter.

Note that when you use autocommit, there is no opportunity for you to explicitly abort the operation. JE, however, will abort the operation if it encounters an error during the write.

For example:

    package je.gettingStarted;

    import com.sleepycat.je.Environment;
    import com.sleepycat.je.EnvironmentConfig;
    import com.sleepycat.je.DatabaseEntry;
    import com.sleepycat.je.DatabaseConfig;
    import com.sleepycat.je.Database;

    import java.io.File;

    ...

    // Open the environment and database such that transactions
    // are supported
    EnvironmentConfig myEnvConfig = new EnvironmentConfig();
    DatabaseConfig myDbConfig = new DatabaseConfig();
    myEnvConfig.setTransactional(true);
    myDbConfig.setTransactional(true);

    Database myDb = null;
    Environment myEnv = null;

    try {
        myEnv =
            new Environment(new File("/my/env/home"), myEnvConfig);

        // This database is opened from within a transaction using autocommit
        // because the database configuration specifies transactions.
        // As a result follow-on database operations can use transactions.
        myDb = myEnv.openDatabase(null, "myDbName", myDbConfig);

        String aKey = "myFirstKey";
        String aData = "myFirstData";

        DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
        DatabaseEntry theData = new DatabaseEntry(aData.getBytes("UTF-8"));

        // This database put is also transactionally protected
        // using autocommit.
        myDb.put(null, theKey, theData);
    } catch (Exception e) {
        // Exception handling goes here.
    }

Prev | Up | Next
Chapter 7. Transactions | Home | Transactional Cursors