Tutorial

Transactions

A Transaction is an atomic, consistent, isolated and durable (“ACID”) unit of work. Transactions guarantee that all database operations of this Transactions are either all written to the database in one atomic “commit” or cancelled and undone in one atomic “abort”. To read more about Transactions, Wikipedia provides a good entry point: http://en.wikipedia.org/wiki/Database_transactions. The following chapter describes the state of Transaction support in upscaledb, and gives a primer how to use them.

upscaledb allows an unlimited number of Transactions to be created in parallel. The Transactions do not block each other in a traditional sense (i.e. they do not block access to the database pages). However, if a Transaction tries to read or modify a key that is currently modified in another active Transaction then the error UPS_TXN_CONFLICT is returned. upscaledb implements the “read-committed” isolation level.

Enabling Transactions

Transaction support has to be explicitly enabled with the flag UPS_ENABLE_TRANSACTIONS when creating or opening an Environment or a Database. The support for Transactions comes with a certain cost regarding performance, because it implicitly enables logging/recovery. The following code enables the use of Transactions:

st = ups_env_create (&env, “test.db”, UPS_ENABLE_TRANSACTIONS, 0644, 0);
if (st != UPS_SUCCESS) {
  printf ("error %d (%s)\n", st, ups_strerror (st));
  exit (–1);
}

Beginning a new Transaction

A new Transaction can be started with ups_txn_begin. The parameter reserved is unused and should be set to NULL. The flags are also unused and should be set to 0. The name is optional and can later be retrieved with ups_txn_get_name.

ups_status_t
ups_txn_begin (ups_txn_t **txn, ups_env_t *env, const char *name,
            void *reserved, uint32_t flags);

API reference for ups_txn_begin

If Transactions were not enabled (with UPS_ENABLE_TRANSACTIONS), the function will return UPS_INV_PARAMETER.

Using Transactions

A Transaction can be used with the following functions:

  • ups_db_insert
  • ups_db_erase
  • ups_db_find
  • ups_cursor_create

In all four cases, the second parameter is the Transaction handle. The following example illustrates how to insert an item with a transactional ups_db_insert; the use of the other three functions is very similar. The changes to the Database are only written if the Transaction is committed! If it is aborted or the application crashes, the changes are not written.

ups_txn_t *txn;
if ((st = ups_txn_begin (&txn, db, 0))) {
  printf (“ups_txn_begin failed: %d (%s)\n”, st, ups_strerror (st));
  exit (–1);
}

st = ups_db_insert (db, txn, key, record, 0);
if (st != UPS_SUCCESS) {
  printf (“ups_db_insert failed: %d (%s)\n”, st, ups_strerror (st));
  exit (–1);
}

In case of ups_cursor_create, the Cursor will be “attached” to the Transaction during its whole lifetime. You have to close the Cursor before committing or aborting the Transaction, otherwise the commit or abort fails with an error.

Committing a Transaction

When committing a Transaction, it is written atomically to the Database. The commit is fairly easy:

ups_status_t 
ups_txn_commit (ups_txn_t *txn, uint32_t flags);

API reference for ups_txn_commit

Again, the flags are not yet used; set them to 0.

st = ups_txn_commit (txn, 0);
if (st != UPS_SUCCESS) {
  printf (“ups_txn_commit failed: %d (%s)\n”, st, ups_strerror (st));
  exit (–1);
}

As mentioned above, the commit will fail with UPS_CURSOR_STILL_OPEN if there are still Cursors attached to this Transaction.

Aborting a Transaction

When aborting a Transaction, all changes are undone. Analog to the commit, aborting a Transaction is simple:

ups_status_t
ups_txn_abort (ups_txn_t *txn, uint32_t flags);

API reference for ups_txn_abort

Again, the flags are not yet used; set them to 0.

st = ups_txn_abort (txn, 0);
if (st != UPS_SUCCESS) {
  printf (“ups_txn_commit failed: %d (%s)\n”, st, ups_strerror(st));
  exit (–1);
}

As mentioned above, the abort will fail with UPS_CURSOR_STILL_OPEN if there are still Cursors attached to this Transaction.