# The eXtreme DB MURSIW Transaction Manager

> As explained in the Fundamental Concepts page, `MURSIW` is a traditional, lock-based transaction manager implemented as a simple queue. And it is important to note that when `MURSIW` is used the only possible Isolation level is `MCO_SERIALIZABLE`. The processing of transactions by `MURSIW` can be affected by setting Transaction Priorities and/or Transaction Scheduling Policy.

> ## Upgrading transactions

> As `MURSIW` uses a queue to process transactions, when a transaction upgrade API is called in the context of an `MCO_UPDATE` transaction, the upgrade is guaranteed to succeed. However, if there is already an `MCO_UPDATE` transaction in the queue or running, when a second `MCO_UPDATE` transaction is requested by the application, the transaction start API will block until the first `MCO_UPDATE` transaction has been completed (committed or rolled back).

> To explain the logic within the `MURSIW` transaction manager implementation consider the following scenarios:

> ### Scenario #1

> If there is a single `MCO_READ_ONLY` transaction running, and the upgrade is requested, the transaction will be immediately promoted to `MCO_READ_WRITE`, even if there is another `MCO_READ_WRITE` transaction in the queue.

> ### Scenario #2

> If there are two (or more) `MCO_READ_ONLY` transactions running and one of them requests an upgrade (calls `mco_trans_upgrade()`), its status in the queue will be changed to `UPDATE` and it will be suspended until the other `MCO_READ_ONLY` transactions are committed or rolled back, then it will be promoted to `MCO_READ_WRITE` and continue executing (even if there are one or more `MCO_READ_WRITE` transactions in the queue).

> ### Scenario #3

> If there are two (or more) `MCO_READ_ONLY` transactions running and two (or more) of them request an upgrade (calls `mco_trans_upgrade()`), the first to request it will succeed and the other(s) will fail. The first will have its status in the queue changed to `UPDATE` and it will be suspended until the other`MCO_READ_ONLY` transactions are committed or rolled back, then it will be promoted to`MCO_READ_WRITE` and continue executing (even if there are one or more `MCO_READ_WRITE` transactions in the queue).

> ### Scenario #4

> There are no other transactions running or in the queue when an `MCO_UPDATE` transaction is started. The transaction enters the queue and is immediately scheduled with `UPDATE` status. Any other transaction (read or write) will be queued. When the upgrade API is called there may be other `MCO_READ_ONLY` or `MCO_READ_WRITE` transactions in the queue, but the `MCO_UPDATE` will be immediately promoted to `MCO_READ_WRITE`, even if the transactions that entered the queue after it are of a higher priority.

> ### Scenario #5

> There is already a transaction running or in the queue with status `UPDATE` when the transaction start API is called with transaction type `MCO_UPDATE`. In this case the transaction start API will block until the `MCO_UPDATE` transaction and all other transactions ahead of it in the queue have completed (committed or rolled back), then the transaction will execute with status `UPDATE`.

> ### Scenario #6

> There is already a transaction in the queue with status `UPDATE` when the upgrade API is called for a transaction of type `MCO_READ_ONLY`. In this case the upgrade API will return error code `MCO_E_UPGRADE_FAIL`.

> So, the transaction types and concurrency with `MURSIW` can be summarized in the following table, where `Y` means that transactions of this type can run concurrently and `N` means that they run in serial:

> | MCO_READ_ONLY | MCO_READ_WRITE | MCO_UPDATE*
> MCO_READ_ONLY | Y | N | Y
> MCO_READ_WRITE | N | N | N
> MCO_UPDATE | Y | N | N

> * after the transaction start API is called and before the upgrade API is called; after the upgrade API the semantics are the same as `MCO_READ_WRITE`.

> Note that a transaction may read, insert, update or delete a single object or many objects, even thousands, depending on the application’s needs. When processing blocks of objects in a single transaction it might happen that an object is deleted, but then before committing the transaction the same object is accessed again. If this occurs the read (get) or update (put) operation, or any other access such as locating the object in a cursor or generating XML on the object, will cause a fatal error code of `MCO_ERR_OBJECT_HANDLE+N` where `N` is a line number in the source code that identifies the exact point where the invalid handle was detected. In order to avoid this fatal error C applications can call the function `mco_is_object_deleted()` to determine if the object was deleted within the current transaction.