The transaction handle
Normally, there is a 1:1 relationship between a transaction handle (trx) and a session (client connection). One session is associated with exactly one user transaction. There are some exceptions to this:
For DDL operations, a subtransaction is allocated that modifies the data dictionary tables. Lock waits and deadlocks are prevented by acquiring the dict_operation_lock before starting the subtransaction and releasing it after committing the subtransaction.
The purge system uses a special transaction that is not associated with any session.
If the system crashed or it was quickly shut down while there were transactions in the ACTIVE or PREPARED state, these transactions would no longer be associated with a session when the server is restarted.
A session may be served by at most one thread at a time. The serving thread of a session might change in some MySQL implementations. Therefore we do not have os_thread_get_curr_id() assertions in the code.
Normally, only the thread that is currently associated with a running transaction may access (read and modify) the trx object, and it may do so without holding any mutex. The following are exceptions to this:
trx_rollback_resurrected() may access resurrected (connectionless) transactions while the system is already processing new user transactions. The trx_sys->mutex prevents a race condition between it and lock_trx_release_locks() [invoked by trx_commit()].
trx_print_low() may access transactions not associated with the current thread. The caller must be holding trx_sys->mutex and lock_sys->mutex.
When a transaction handle is in the trx_sys->mysql_trx_list or trx_sys->trx_list, some of its fields must not be modified without holding trx_sys->mutex exclusively.
The locking code (in particular, lock_deadlock_recursive() and lock_rec_convert_impl_to_expl()) will access transactions associated to other connections. The locks of transactions are protected by lock_sys->mutex and sometimes by trx->mutex.
Definition at line 676 of file trx0trx.h.
State of the trx from the point of view of concurrency control
and the valid state transitions.
Possible states:
TRX_STATE_NOT_STARTED TRX_STATE_ACTIVE TRX_STATE_PREPARED TRX_STATE_COMMITTED_IN_MEMORY (alias below COMMITTED)
Valid state transitions are:
Regular transactions: NOT_STARTED -> ACTIVE -> COMMITTED -> NOT_STARTED
Auto-commit non-locking read-only: NOT_STARTED -> ACTIVE -> NOT_STARTED
XA (2PC): NOT_STARTED -> ACTIVE -> PREPARED -> COMMITTED -> NOT_STARTED
Recovered XA: NOT_STARTED -> PREPARED -> COMMITTED -> (freed)
XA (2PC) (shutdown before ROLLBACK or COMMIT): NOT_STARTED -> PREPARED -> (freed)
Latching and various transaction lists membership rules:
XA (2PC) transactions are always treated as non-autocommit.
Transitions to ACTIVE or NOT_STARTED occur when !in_rw_trx_list and !in_ro_trx_list (no trx_sys->mutex needed).
Autocommit non-locking read-only transactions move between states without holding any mutex. They are !in_rw_trx_list, !in_ro_trx_list.
When a transaction is NOT_STARTED, it can be in_mysql_trx_list if it is a user transaction. It cannot be in ro_trx_list or rw_trx_list.
ACTIVE->PREPARED->COMMITTED is only possible when trx->in_rw_trx_list. The transition ACTIVE->PREPARED is protected by trx_sys->mutex.
ACTIVE->COMMITTED is possible when the transaction is in ro_trx_list or rw_trx_list.
Transitions to COMMITTED are protected by both lock_sys->mutex and trx->mutex.
NOTE: Some of these state change constraints are an overkill, currently only required for a consistent view for printing stats. This unnecessarily adds a huge cost for the general case.
NOTE: In the future we should add read only transactions to the ro_trx_list the first time they try to acquire a lock ie. by default we treat all read-only transactions as non-locking.
Definition at line 740 of file trx0trx.h.