NexusDB use different kinds of locking to perform optimally in multi user environments.

Content Locks

Content locks can be either record-level (these are always write locks, acquired by calling Edit) or table-level (these can be either read or write locks, acquired by calling LockTable).

Content locks can be contending for the same resource. If so, then an existing record-level content lock can prevent table-level content locks from being granted.  Similarly a table-level content lock will prevent a record-level content lock from being granted.

In NexusDB only one cursor can own a write lock on the same table. Many cursors can own a read lock  As long as any cursor holds a read lock no write lock can be placed on the table.  Table level locks interact with record level locks.  Record level locks are always write locks.  You cannot acquire a table level read lock if any cursor holds a record  lock.  You cannot acquire a table level write lock if any OTHER cursor holds a  record lock. You can only acquire a record lock if there are no table level locks or if  you own a table level write lock.

A table level read lock prevents anyone including yourself from changing the  table while you hold the lock. A table level write lock prevents anyone else from changing the table while  you hold the lock.

Transaction Locks

Transaction locks are independent from content locks.  A shared transaction lock is acquired when you read from a table in the context of a transaction.  An exclusive transaction lock is acquired when you write to a table in the context of a transaction.

How are locks implemented?

Each server side table object has 2 different synchronization objects that manage access to the table:

TnxLockContainer

TnxLockContainer handles transaction locking (shared/exclusive locks).  This lock container is only used when the table is accessed in the context of a transaction.  Read access needs a shared lock.  Write access requires an exclusive lock.  At any point in time there can be no locks, a single or multiple shared locks or a single exclusive lock.  No other combination is possible.

TnxReadWritePortal

TnxReadWritePortal handles thread synchronization.  Each thread that wants to read from the table outside of a transaction must acquire a read lock on this portal.  (This read lock is always released before a server call returns to the client.  It is only acquired for the split second it takes to perform the actual read of a single record).  A thread that wants to commit a transaction which has acquired an exclusive lock on the table must acquire a write lock on this portal before it can commit its changes.  This is needed to prevent reading threads from accessing the buffer manager while memory pages are copied from the transaction buffers into the real buffers.

In summary there can be different types of access to a table:

Read access

In the context of a transaction this acquires a shared lock until the transaction is completed.  Outside a transaction read access acquires a read lock on the table for the split second it takes to actually perform the read.

Write access

This can only be done in the context of a transaction (a transaction is automatically started and immediately committed if no active transaction is present).  Write access will acquire an exclusive lock until the transaction is completed and committed.  It also requires an active transaction (which has already acquired an exclusive lock, preventing read access from inside other transactions) and acquires a write lock (preventing reads from outside a transaction) for the time it takes to commit the changes to disk.

Transaction isolation levels

First a quick description of the different possible isolation levels:

READ UNCOMMITTED or DIRTY READ

You can read an uncommitted transaction that might get rolled back later.  This isolation level is also called a dirty read.  This is the lowest isolation level.

READ COMMITTED

This ensures that data that another application has changed and not yet committed can not be read, but it does not ensure that the data will not be changed before the end of the current transaction.

NON REPEATABLE READ

This occurs when a transaction reads the same record more than once and, between the two (or more) reads, a separate transaction modifies that record.  Because the record was modified between reads within the same transaction, each read produces different values, which introduces inconsistency.

REPEATABLE READ

When it's used, then dirty reads and no repeatable reads cannot occur.

PHANTOM

Phantom behavior occurs when a transaction attempts to read a record that does not exist and a second transaction inserts the record before the first transaction finishes.  If the record is inserted, the record appears as a phantom to the first transaction, inconsistently appearing and disappearing.

SERIALIZABLE

This is the most restrictive isolation level.  When used, phantom values cannot occur.  It prevents other users from updating or inserting records into the data set until the transaction is complete.

There is only one physical type of transaction in NexusDB.  The distinction between implicit and explicit transactions is a virtual one.  Any operation that results in write access to a table, checks if a transaction is already present.  If not present, then a transaction is started (implicit), the operation performed (insert, modify, delete) and the transaction committed/rolled back depending on the success of the operation.

An explicit transaction is a client side controlled transaction.

Using the above terminology, we can now classify NexusDB as follows:

Dataset state or context

NexusDB

outside of an explicit transaction

read committed

in the context of an explicit transaction

serializable

locking granularity

table level

Home | Site Contents | Documentation | NexusDB Manual V4 | Architecture and Concepts | NexusDB Concepts | Transactions and Data Integrity