MySQL 9.0.0
Source Code Documentation
locksys Namespace Reference

Classes

struct  Conflicting
 
class  Global_exclusive_latch_guard
 A RAII helper which latches global_latch in exclusive mode during constructor, and unlatches it during destruction, preventing any other threads from activity within lock_sys for it's entire scope. More...
 
class  Global_exclusive_try_latch
 A RAII helper which tries to exclusively latch the global_lach in constructor and unlatches it, if needed, during destruction, preventing any other threads from activity within lock_sys for it's entire scope, if owns_lock(). More...
 
class  Global_shared_latch_guard
 A RAII helper which latches global_latch in shared mode during constructor, and unlatches it during destruction, preventing any other thread from acquiring exclusive latch. More...
 
class  Latches
 The class which handles the logic of latching of lock_sys queues themselves. More...
 
class  Shard_latch_guard
 A RAII wrapper class which combines Global_shared_latch_guard and Shard_naked_latch_guard to s-latch the global lock_sys latch and latch the mutex protecting the specified shard for the duration of its scope. More...
 
class  Shard_latches_guard
 A RAII wrapper class which s-latches the global lock_sys shard, and mutexes protecting specified shards for the duration of its scope. More...
 
class  Shard_naked_latch_guard
 A RAII helper which latches the mutex protecting given shard during constructor, and unlatches it during destruction. More...
 
class  Shard_naked_latches_guard
 A RAII helper which latches the mutexes protecting specified shards for the duration of its scope. More...
 
class  Trx_locks_cache
 An object which can be passed to consecutive calls to rec_lock_has_to_wait(trx, mode, lock, is_supremum, trx_locks_cache) for the same trx and heap_no (which is implicitly the bit common to all lock objects passed) which can be used by this function to cache some partial results. More...
 
class  Unsafe_global_latch_manipulator
 

Enumerations

enum class  Conflict { HAS_TO_WAIT , NO_CONFLICT , CAN_BYPASS }
 

Functions

bool has_to_wait (const lock_t *lock1, const lock_t *lock2, Trx_locks_cache &lock1_cache)
 Checks if a lock request lock1 has to wait for request lock2. More...
 
bool owns_exclusive_global_latch ()
 Tests if lock_sys latch is exclusively owned by the current thread. More...
 
bool owns_shared_global_latch ()
 Tests if lock_sys latch is owned in shared mode by the current thread. More...
 
bool owns_page_shard (const page_id_t &page_id)
 Tests if given page shard can be safely accessed by the current thread. More...
 
bool owns_table_shard (const dict_table_t &table)
 Test if given table shard can be safely accessed by the current thread. More...
 
bool owns_lock_shard (const lock_t *lock)
 Checks if shard which contains lock is latched (or that an exclusive latch on whole lock_sys is held) by current thread. More...
 
template<typename F >
auto latch_peeked_shard_and_do (const lock_t *peeked_lock, F &&f)
 Temporarily releases trx->mutex, latches the lock-sys shard containing peeked_lock and latches trx->mutex again and calls f under protection of both latches. More...
 
template<typename F >
void run_if_waiting (const TrxVersion trx_version, F &&f)
 Given a pointer to trx (which the caller guarantees will not be freed) and the expected value of trx->version, will call the provided function f, only if the trx is still in expected version and waiting for a lock, within a critical section which holds latches on the trx, and the shard containing the waiting lock. More...
 
static Conflict rec_lock_check_conflict (const trx_t *trx, ulint type_mode, const lock_t *lock2, bool lock_is_on_supremum, Trx_locks_cache &trx_locks_cache)
 Checks if a new request for a record lock has to wait for existing request. More...
 
static bool rec_lock_has_to_wait (const lock_t *lock1, const lock_t *lock2, Trx_locks_cache &lock1_cache)
 Checks if a record lock request lock1 has to wait for request lock2. More...
 
static void add_to_trx_locks (lock_t *lock)
 Adds the lock to the list of trx's locks. More...
 
static void remove_from_trx_locks (lock_t *lock)
 Removes the lock from the list of trx's locks. More...
 
template<typename F >
static bool try_relatch_trx_and_shard_and_do (const lock_t *lock, F &&f)
 A helper function which solves a chicken-and-egg problem occurring when one needs to iterate over trx's locks and perform some actions on them. More...
 
static bool try_release_read_locks_in_s_mode (trx_t *trx, bool only_gap)
 Tries to release read locks of a transaction without latching the whole lock sys. More...
 
static bool try_release_read_locks_in_x_mode (trx_t *trx, bool only_gap)
 Release read locks of a transaction latching the whole lock-sys in exclusive mode, which is a bit too expensive to do by default. More...
 
static bool try_release_all_locks (trx_t *trx)
 Releases transaction locks, and releases possible other transactions waiting because of these locks. More...
 
static void rec_queue_validate_latched (const buf_block_t *block, const rec_t *rec, const dict_index_t *index, const ulint *offsets)
 Validates the lock queue on a single record. More...
 
static void rec_queue_latch_and_validate (const buf_block_t *block, const rec_t *rec, const dict_index_t *index, const ulint *offsets)
 Validates the lock queue on a single record. More...
 
static void rec_queue_latch_and_validate (const buf_block_t *block, const rec_t *rec, const dict_index_t *index)
 Validates the lock queue on a single record. More...
 

Variables

constexpr auto MAX_CS_DURATION = std::chrono::seconds{1}
 We don't want to hold the Global latch for too long, even in S mode, not to starve threads waiting for X-latch on it such as lock_wait_timeout_thread(). More...
 

Enumeration Type Documentation

◆ Conflict

enum class locksys::Conflict
strong
Enumerator
HAS_TO_WAIT 
NO_CONFLICT 
CAN_BYPASS 

Function Documentation

◆ add_to_trx_locks()

static void locksys::add_to_trx_locks ( lock_t lock)
static

Adds the lock to the list of trx's locks.

Requires lock->trx to be already set. Bumps the trx_lock_version.

Parameters
[in,out]lockThe lock that we want to add to lock->trx->lock.trx_locks

◆ has_to_wait()

bool locksys::has_to_wait ( const lock_t lock1,
const lock_t lock2,
Trx_locks_cache lock1_cache 
)

Checks if a lock request lock1 has to wait for request lock2.

It returns the same result as

See also
lock_has_to_wait(lock1, lock2), but in case these are record locks, it might use lock1_cache object to speed up the computation. If the same lock1_cache is passed to multiple calls of this method, then lock1 also needs to be the same.
Parameters
[in]lock1A waiting lock
[in]lock2Another lock; NOTE that it is assumed that this has a lock bit set on the same record as in lock1 if the locks are record locks.
[in]lock1_cacheAn object which can be passed to consecutive calls to this function for the same lock1 which can be used by this function to cache some partial results.
Returns
true if lock1 has to wait for lock2 to be removed

◆ latch_peeked_shard_and_do()

template<typename F >
auto locksys::latch_peeked_shard_and_do ( const lock_t peeked_lock,
F &&  f 
)

Temporarily releases trx->mutex, latches the lock-sys shard containing peeked_lock and latches trx->mutex again and calls f under protection of both latches.

The latch on lock-sys shard will be released immediately after f returns. It is a responsibility of the caller to handle shared lock-sys latch, trx->mutex and verify inside f that the trx has not been finished, and the lock was not released meanwhile.

Parameters
[in]peeked_lockA lock of the trx. (While trx->mutex is held it can't be freed, but can be released). It is used to determine the lock-sys shard to latch.
[in]fThe callback to call once the lock-sys shard is latched and trx->mutex is relatched.
Returns
The value returned by f.

◆ owns_exclusive_global_latch()

bool locksys::owns_exclusive_global_latch ( )

Tests if lock_sys latch is exclusively owned by the current thread.

Returns
true iff the current thread owns exclusive global lock_sys latch

◆ owns_lock_shard()

bool locksys::owns_lock_shard ( const lock_t lock)

Checks if shard which contains lock is latched (or that an exclusive latch on whole lock_sys is held) by current thread.

Parameters
[in]locklock which belongs to a shard we want to check
Returns
true iff the current thread owns exclusive global lock_sys latch or both a shared global lock_sys latch and mutex protecting the shard containing the specified lock

◆ owns_page_shard()

bool locksys::owns_page_shard ( const page_id_t page_id)

Tests if given page shard can be safely accessed by the current thread.

Parameters
page_idspecifies the page
Returns
true iff the current thread owns exclusive global lock_sys latch or both a shared global lock_sys latch and mutex protecting the page shard

◆ owns_shared_global_latch()

bool locksys::owns_shared_global_latch ( )

Tests if lock_sys latch is owned in shared mode by the current thread.

Returns
true iff the current thread owns shared global lock_sys latch

◆ owns_table_shard()

bool locksys::owns_table_shard ( const dict_table_t table)

Test if given table shard can be safely accessed by the current thread.

Parameters
tablethe table
Returns
true iff the current thread owns exclusive global lock_sys latch or both a shared global lock_sys latch and mutex protecting the table shard

◆ rec_lock_check_conflict()

static Conflict locksys::rec_lock_check_conflict ( const trx_t trx,
ulint  type_mode,
const lock_t lock2,
bool  lock_is_on_supremum,
Trx_locks_cache trx_locks_cache 
)
inlinestatic

Checks if a new request for a record lock has to wait for existing request.

Parameters
[in]trxThe trx requesting the new lock
[in]type_modeprecise mode of the new lock to set: LOCK_S or LOCK_X, possibly ORed to LOCK_GAP or LOCK_REC_NOT_GAP, LOCK_INSERT_INTENTION
[in]lock2another record lock; NOTE that it is assumed that this has a lock bit set on the same record as in the new lock we are setting
[in]lock_is_on_supremumtrue if we are setting the lock on the 'supremum' record of an index page: we know then that the lock request is really for a 'gap' type lock
[in]trx_locks_cacheAn object which can be passed to consecutive calls to this function for the same trx and heap_no (which is implicitly the bit common to all lock2 objects passed) which can be used by this function to cache some partial results.
Return values
NO_CONFLICTthe trx does not have to wait for lock2
CAN_BYPASSthe trx does not have to wait for lock2, as it can bypass it
HAS_TO_WAITthe trx has to wait for lock2

◆ rec_lock_has_to_wait()

static bool locksys::rec_lock_has_to_wait ( const lock_t lock1,
const lock_t lock2,
Trx_locks_cache lock1_cache 
)
inlinestatic

Checks if a record lock request lock1 has to wait for request lock2.

Parameters
[in]lock1waiting record lock
[in]lock2another record lock; NOTE that it is assumed that this has a lock bit set on the same record as in lock1
[in]lock1_cacheCached info gathered during calls with lock1
Returns
true if lock1 has to wait for lock2 to be removed

◆ rec_queue_latch_and_validate() [1/2]

static void locksys::rec_queue_latch_and_validate ( const buf_block_t block,
const rec_t rec,
const dict_index_t index 
)
static

Validates the lock queue on a single record.

Parameters
[in]blockbuffer block containing rec
[in]recrecord to look at
[in]indexindex, or NULL if not known

◆ rec_queue_latch_and_validate() [2/2]

static void locksys::rec_queue_latch_and_validate ( const buf_block_t block,
const rec_t rec,
const dict_index_t index,
const ulint offsets 
)
static

Validates the lock queue on a single record.

Parameters
[in]blockbuffer block containing rec
[in]recrecord to look at
[in]indexindex, or NULL if not known
[in]offsetsrec_get_offsets(rec, index)

◆ rec_queue_validate_latched()

static void locksys::rec_queue_validate_latched ( const buf_block_t block,
const rec_t rec,
const dict_index_t index,
const ulint offsets 
)
static

Validates the lock queue on a single record.

Parameters
[in]blockbuffer block containing rec
[in]recrecord to look at
[in]indexindex, or NULL if not known
[in]offsetsrec_get_offsets(rec, index)

◆ remove_from_trx_locks()

static void locksys::remove_from_trx_locks ( lock_t lock)
static

Removes the lock from the list of trx's locks.

Bumps the trx_lock_version.

Parameters
[in,out]lockThe lock that we want to remove from lock->trx->lock.trx_locks

◆ run_if_waiting()

template<typename F >
void locksys::run_if_waiting ( const TrxVersion  trx_version,
F &&  f 
)

Given a pointer to trx (which the caller guarantees will not be freed) and the expected value of trx->version, will call the provided function f, only if the trx is still in expected version and waiting for a lock, within a critical section which holds latches on the trx, and the shard containing the waiting lock.

If the transaction has meanwhile finished waiting for a lock, or committed or rolled back etc. the f will not be called. It may happen that the lock for which the trx is waiting during exectuion of f is not the same as the lock it was waiting at the moment of invocation.

Parameters
[in]trx_versionThe version of the trx that we intend to wake up
[in]fThe callback to call if trx is still waiting for a lock and is still in version trx_version

◆ try_relatch_trx_and_shard_and_do()

template<typename F >
static bool locksys::try_relatch_trx_and_shard_and_do ( const lock_t lock,
F &&  f 
)
static

A helper function which solves a chicken-and-egg problem occurring when one needs to iterate over trx's locks and perform some actions on them.

Iterating over this list requires trx->mutex (or exclusive global lock_sys latch), and operating on a lock requires lock_sys latches, yet the latching order requires lock_sys latches to be taken before trx->mutex. One way around it is to use exclusive global lock_sys latch, which heavily deteriorates concurrency. Another is to try to reacquire the latches in needed order, veryfing that the list wasn't modified meanwhile. This function performs following steps:

  1. releases trx->mutex,
  2. acquires proper lock_sys shard latch for given lock,
  3. reaquires trx->mutex
  4. executes f unless trx's locks list has changed Before and after this function following should hold:
  • the shared global lock_sys latch is held
  • the trx->mutex is held
    Parameters
    [in]lockthe lock we are interested in
    [in]fthe function to execute when the shard is latched
    Returns
    true if f was called, false if it couldn't be called because trx locks have changed while relatching trx->mutex

◆ try_release_all_locks()

static bool locksys::try_release_all_locks ( trx_t trx)
static

Releases transaction locks, and releases possible other transactions waiting because of these locks.

Parameters
[in,out]trxtransaction
Returns
true if and only if it succeeded to do the job

◆ try_release_read_locks_in_s_mode()

static bool locksys::try_release_read_locks_in_s_mode ( trx_t trx,
bool  only_gap 
)
static

Tries to release read locks of a transaction without latching the whole lock sys.

This may fail, if there are many concurrent threads editing the list of locks of this transaction (for example due to B-tree pages being merged or split, or due to implicit-to-explicit conversion). It is called during XA prepare to release locks early.

Parameters
[in,out]trxtransaction
[in]only_gaprelease only GAP locks
Returns
true if and only if it succeeded to do the job

◆ try_release_read_locks_in_x_mode()

static bool locksys::try_release_read_locks_in_x_mode ( trx_t trx,
bool  only_gap 
)
static

Release read locks of a transaction latching the whole lock-sys in exclusive mode, which is a bit too expensive to do by default.

It is called during XA prepare to release locks early.

Parameters
[in,out]trxtransaction
[in]only_gaprelease only GAP locks
Returns
true if and only if it succeeded to do the job

Variable Documentation

◆ MAX_CS_DURATION

constexpr auto locksys::MAX_CS_DURATION = std::chrono::seconds{1}
constexpr

We don't want to hold the Global latch for too long, even in S mode, not to starve threads waiting for X-latch on it such as lock_wait_timeout_thread().

This defines the longest allowed critical section duration.