Extensible Storage Engine - Transactions

Transactions

A transaction is a logical unit of processing delimited by BeginTransaction and CommitTransaction, or Rollback, operations. All updates performed during a transaction are atomic; they either all appear in the database at the same time or none appear. Any subsequent updates by other transactions are invisible to a transaction. However, a transaction can update only data that has not changed in the meantime; else the operation fails at once without waiting. Read-only transactions never need to wait, and update transactions can interfere only with one another updating transaction. Transactions which are terminated by Rollback, or by a system crash, leave no trace on the database. In general, the data state is restored on Rollback to what it was prior to BeginTransaction.

Transactions may be nested up to 7 levels, with one additional level reserved for ESE internal use. This means that a part of a transaction may be rolled back, without need to roll back the entire transaction; a CommitTransaction of a nested transaction merely signifies the success of one phase of processing, and the outer transaction may yet fail. Changes are committed to the database only when the outermost transaction is committed. This is known as committing to transaction level 0. When the transaction commits to transaction level 0, data describing the transaction is synchronously flushed to the log to ensure that the transaction will be completed even in the event of a subsequent system crash. Synchronously flushing the log makes ESE transactions durable. However, in some cases application wish to order their updates, but not immediately guarantee that changes will be done. Here, applications can commit changes with JET_bitIndexLazyFlush.

ESE supports a concurrency control mechanism called multi-versioning. In multi-versioning, every transaction queries a consistent view of the entire database as it was at the time the transaction started. The only updates it encounters are those made by it. In this way, each transaction operates as though it was the only active transaction running on the system, except in the case of write conflicts. Since a transaction may make changes based on data read that has already been updated in another transaction, multi-versioning by itself does not guarantee serializable transactions. However, serializability can be achieved when desired by simply using explicit record read locks to lock read data that updates are based upon. Both read and write locks may be explicitly requested with the GetLock operation.

In addition, an advanced concurrency control feature known as escrow locking is supported by ESE. Escrow locking is an extremely concurrent update where a numeric value is changed in a relative fashion, i.e. by adding or subtracting another numeric value. Escrow updates are non-conflicting even with other concurrent escrow updates to the same datum. This is possible because the operations supported are commutable and can be independently committed or rolled back. As a result, they do not interfere with concurrent update transactions. This feature is often used for maintained aggregations.

ESE also extends transaction semantics from data manipulation operations to data definition operations. It is possible to add an index to a table and have concurrently running transactions update the same table without any transaction lock contention whatsoever. Later, when these transactions are complete, the newly created index is available to all transactions and has entries for record updates made by other transactions that could not perceive the presence of the index when the updates took place. Data definition operations may be performed with all the features expected of the transaction mechanism for record updates. Data definition operations supported in this fashion include AddColumn, DeleteColumn, CreateIndex, DeleteIndex, CreateTable and DeleteTable.

Read more about this topic:  Extensible Storage Engine