"Content locks" on both table and record level are something fundamentally different then "transaction locks".

When you call Edit you place an "exclusive record level content lock".

If you call LockTable(nxltReadLock) you place an "shared table level content lock".

If you call LockTable(nxltWriteLock) you place an "exclusive table level content lock".

At any one time, per table, you can have either:

- 1 or more shared table level locks

- 1 exclusive table level lock and 0 or more exclusive record locks from the same cursor

- 1 or more exclusive record locks from different clients *but not for the same record*

- no locks at all

Content locks "belong" to a single cursor. If you have 2 TnxTable in your application you can not put the same record in edit mode on both. The locks conflict.

Whenever you try to acquire a content lock of any kind, if that lock would lead to a situation not covered in the list above it waits until the lock can be granted because conflicting locks have been released or until timeout. Whichever happens first.

In addition to the above. When a content lock, no matter of record or table level gets released in the context of a transaction. Then ALL

attempts to acquire new content locks, no matter which type, have to wait for that transaction to finish.

The reason for that is, if you have a transaction, and you successfully edit/posted a record, then it must be possible for you to go back to that record later and edit it again.

Now on to "transaction locks".

Transaction locks come in 2 flavors, exclusive and shared. Simply speaking, you need a shared lock to read from a table and an exclusive lock to write into a table.

When you call StartTransactionWith then the call only succeeds if exclusive transaction locks can be acquired for all listed tables.

Once a transaction is active, no matter if started with StartTransaction or StartTransactionWith, additional transaction locks are acquired fully automatically as needed. So if you access a table that was not listed in StartTransactionWith in the context of such a transaction then additional locks will be acquired.

At any time there can be, per "data dictionary" (all tables defined in the same dictionary are grouped together here), either:

- 1 or more shared transaction locks

- 1 exclusive transaction lock

- no locks

Transaction locks "belong" to a transaction context. You can have any number of cursors (TnxTable / TnxQuery) that access the same table at the same time as long as they share the same transaction context (basically, are attached to the same TnxDatabase instance).

Whenever you try to acquire a transaction lock of any kind, if that lock would lead to a situation not covered in the list above it waits until the lock can be granted because conflicting locks have been released or until timeout. Whichever happens first. In addition there is some code in place which can detect certain types of deadlocks, e.g. 2 transactions, both having a shared lock on the same table, both trying to "upgrade" to an exclusive lock. One of the transactions will instantly get a DBIERR_DEADLOCKED the other will get it's lock granted.

If you try to read, in the context of a transaction, from a table for which you currently don't hold at least a shared lock, then a shared locks needs to be acquired for this read access. If there is a conflict then the read operation (Next, Prior, Last, First, FindKey, SetRange, ...) will wait until timeout or until the lock can be granted.

If you try to write, in the context of a transaction, to a table for which you currently don't hold an exclusive lock then an exclusive lock needs to be acquired for this write access. If there is a conflict then the write operation (Post) will wait until timeout, until a deadlock is detected or until the lock can be granted.

*** Transaction locks and content locks do NOT interact with each other in any way. ***

*** Releasing a content lock in the context of a transaction will prevent all other content locks on that table from being acquired until the transaction is finished. But it does NOT conflict with content locks that may already exist. ***

Last point, if you don't have an active transaction of your own:

Read access is always possible. It will never block (except for a few msec during the commit of another transaction while some internal data structures are updated). You will never see "uncommitted" data. But between 2 reads a commit from another transaction might have taken place so the data you see can change between 2 reads.

Write access (Post) ALWAYS required an transaction. If there is no active transaction then the server internally starts a transaction, performs the post, and commits or rollbacks that transaction depending on the outcome of the post. ALL the normal rules about transactions and transaction locks apply for this implicit transaction. Except for the fact that the server starts and commits/rollbacks it for you there is NO difference between such an implicit transaction and one that you start

yourself.

Home | Site Contents | Documentation | NexusDB Manual V4 | Delphi Guide | Code Examples & Fragments