Chapter 8. Using Transactions

Table of Contents

Initializing the Transactional Subsystem
Transactionally Protecting Container Operations
Transactions Considerations
Transaction Disk I/O
Transaction and Lock Contention
Index Operations and Transactions

Transactions allow you to treat one or more operations on one or more containers as a single unit of work. The BDB XML transactional subsystem is simply a wrapper around Berkeley DB's transactional subsystem. This means that you BDB XML offers the same, full, ACID protection as does Berkeley DB. That is, BDB XML transactions offer you:

Transactionally processing is covered in great detail in the Berkeley DB Programmer's Reference Guide. All of the concepts and topics described there are relevant to transactionally protecting an BDB XML application.

The next few sections describe topics that are specific to transactionally protecting a BDB XML application.

Initializing the Transactional Subsystem

In order to use transactions, you must turn on the transactional subsystem. You do this when you open your XmlManager by setting the appropriate configuration options for the manager. You must also turn on transactions for your container when you open it, again through the use of the appropriate configuration options.

Note that if you do not enable transactions when you first create your environment, then you cannot subsequently use transactions. Also, if your environment is not opened to support transactions, then your containers cannot be opened to support transactions. Finally, you cannot transactionally protect your container operations unless your environment and containers are configured to support transactions.

One final point: the default XmlManager constructor does not enable the transactional subsystem for its underlying environment, and there is no way to pass the appropriate configuration options to that environment using the default constructor. Instead, you must construct your own DbEnv object, passing it the configuration options required to enable transactions, and then hand that DbEnv object to the XmlManager constructor.

In order to enable transactions, you must enable the memory pool (the cache), the logging subsystem, the locking subsystem, and the transactional subsystem. For example:

package dbxml.gettingStarted;

import com.sleepycat.db.DatabaseException;
import com.sleepycat.db.Environment;
import com.sleepycat.db.EnvironmentConfig;

import com.sleepycat.dbxml.XmlException;
import com.sleepycat.dbxml.XmlManager;
import com.sleepycat.dbxml.XmlManagerConfig;
                                                                                                                                  
import java.io.File;
import java.io.FileNotFoundException;
                                                                                                                                  
...
                                                                                                                                  
Environment myEnv = null;
File envHome = new File("/export1/testEnv");
XmlManager myManager = null;
try {
    EnvironmentConfig envConf = new EnvironmentConfig();
    envConf.setAllowCreate(true);         // If the environment does not
                                          // exits, create it.
    envConf.setInitializeCache(true);     // Turn on the shared memory
                                          // region.
    envConf.setInitializeLocking(true);   // Turn on the locking subsystem.
    envConf.setInitializeLogging(true);   // Turn on the logging subsystem.
    envConf.setTransactional(true);       // Turn on the transactional 
                                          // subsystem.

    myEnv = new Environment(envHome, envConf);

    XmlManagerConfig managerConfig = new XmlManagerConfig();
    myManager = new XmlManager(myEnv, managerConfig);

} catch (DatabaseException de) {
    // Exception handling goes here
} catch (FileNotFoundException fnfe) {
    // Exception handling goes here
} catch (XmlException e) {
    // Exception handling goes here
} finally {
    try {
        if (myManager != null) {
            myManager.close();
        }
        if (myEnv != null) {
            myEnv.close();
        }
    } catch (XmlException ce) {
        // Exception handling goes here
    } catch (DatabaseException de) {
        // Exception handling goes here
    }
} 

Once you have enabled transactions for your environment and your manager, you must enable transactions for the containers that you open. You do this by EnvironmentConfig.setTransactional() to true when you create or open the container.

The following code updates the previous example to also open a container. The new code is shown in bold.

package dbxml.gettingStarted;

import com.sleepycat.db.DatabaseException;
import com.sleepycat.db.Environment;
import com.sleepycat.db.EnvironmentConfig;

import com.sleepycat.dbxml.XmlContainer;
import com.sleepycat.dbxml.XmlContainerConfig;
import com.sleepycat.dbxml.XmlException;
import com.sleepycat.dbxml.XmlManager;
import com.sleepycat.dbxml.XmlManagerConfig;
                                                                                                                                  
import java.io.File;
import java.io.FileNotFoundException;
                                                                                                                                  
...
                                                                                                                                  
Environment myEnv = null;
File envHome = new File("/export1/testEnv");
XmlManager myManager = null;
XmlContainer myContainer = null;
try {
    EnvironmentConfig envConf = new EnvironmentConfig();
    envConf.setAllowCreate(true);         // If the environment does not
                                          // exits, create it.
    envConf.setInitializeCache(true);     // Turn on the shared memory
                                          // region.
    envConf.setInitializeLocking(true);   // Turn on the locking subsystem.
    envConf.setInitializeLogging(true);   // Turn on the logging subsystem.
    envConf.setTransactional(true);       // Turn on the transactional 
                                          // subsystem.

    myEnv = new Environment(envHome, envConf);

    myManager = new XmlManager(myEnv);

    XmlContainerConfig containerConf = new XmlContainerConfig();
    containerConf.setTransactional(true);
    containerConf.setAllowCreate(true);
    String containerName = "myContainer.dbxml";
    myContainer = myManager.openContainer(containerName, containerConf); 

} catch (DatabaseException de) {
    // Exception handling goes here
} catch (FileNotFoundException fnfe) {
    // Exception handling goes here
} catch (XmlException e) {
    // Exception handling goes here
} finally {
    try {
        if (myManager != null) {
            myManager.close();
        }
        if (myEnv != null) {
            myEnv.close();
        }
    } catch (XmlException ce) {
        // Exception handling goes here
    } catch (DatabaseException de) {
        // Exception handling goes here
    }
}