MySQL  8.0.21
Source Code Documentation
lock0lock.cc File Reference

The transaction lock system. More...

#include <mysql/service_thd_engine_lock.h>
#include <sys/types.h>
#include <algorithm>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "btr0btr.h"
#include "current_thd.h"
#include "debug_sync.h"
#include "dict0boot.h"
#include "dict0mem.h"
#include "ha_prototypes.h"
#include "lock0lock.h"
#include "lock0priv.h"
#include "pars0pars.h"
#include "row0mysql.h"
#include "row0sel.h"
#include "srv0mon.h"
#include "trx0purge.h"
#include "trx0sys.h"
#include "usr0sess.h"
#include "ut0new.h"
#include "ut0vec.h"
#include "my_dbug.h"
#include "my_psi_config.h"
#include "mysql/plugin.h"
#include "mysql/psi/psi_thread.h"

Classes

class  Deadlock_notifier
 A static class for reporting notifications about deadlocks. More...
 
struct  TableLockGetNode
 Functor for accessing the embedded node within a table lock. More...
 
struct  PrintNotStarted
 Functor to print not-started transaction from the mysql_trx_list. More...
 
class  TrxLockIterator
 Iterate over a transaction's locks. More...
 
class  TrxListIterator
 This iterates over both the RW and RO trx_sys lists. More...
 

Namespaces

 locksys
 

Macros

#define LOCK_MODULE_IMPLEMENTATION
 
#define IS_LOCK_S_OR_X(lock)   (lock_get_mode(lock) == LOCK_S || lock_get_mode(lock) == LOCK_X)
 
#define PRINT_NUM_OF_LOCK_STRUCTS
 

Typedefs

template<typename T >
using Locks = std::vector< T, mem_heap_allocator< T > >
 

Functions

bool locksys::owns_exclusive_global_latch ()
 Tests if lock_sys latch is exclusively owned by the current thread. More...
 
bool locksys::owns_shared_global_latch ()
 Tests if lock_sys latch is owned in shared mode by the current thread. More...
 
bool locksys::owns_page_shard (const page_id_t &page_id)
 Tests if given page shard can be safely accessed by the current thread. More...
 
bool locksys::owns_table_shard (const dict_table_t &table)
 Test if given table shard can be safely accessed by the current thread. More...
 
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. More...
 
static bool lock_rec_validate_page (const buf_block_t *block)
 Validates the record lock queues on a page. More...
 
void lock_report_trx_id_insanity (trx_id_t trx_id, const rec_t *rec, const dict_index_t *index, const ulint *offsets, trx_id_t max_trx_id)
 Reports that a transaction id is insensible, i.e., in the future. More...
 
bool lock_check_trx_id_sanity (trx_id_t trx_id, const rec_t *rec, const dict_index_t *index, const ulint *offsets)
 Checks that a transaction id is sensible, i.e., not in the future. More...
 
bool lock_clust_rec_cons_read_sees (const rec_t *rec, dict_index_t *index, const ulint *offsets, ReadView *view)
 Checks that a record is seen in a consistent read. More...
 
bool lock_sec_rec_cons_read_sees (const rec_t *rec, const dict_index_t *index, const ReadView *view)
 Checks that a non-clustered index record is seen in a consistent read. More...
 
void lock_sys_create (ulint n_cells)
 Creates the lock system at database start. More...
 
static ulint lock_rec_lock_fold (const lock_t *lock)
 Calculates the fold value of a lock: used in migrating the hash table. More...
 
void lock_sys_resize (ulint n_cells)
 Resize the lock hash tables. More...
 
void lock_sys_close (void)
 Closes the lock system at database shutdown. More...
 
ulint lock_get_size (void)
 Gets the size of a lock struct. More...
 
UNIV_INLINE void lock_set_lock_and_trx_wait (lock_t *lock)
 Sets the wait flag of a lock and the back pointer in trx to lock. More...
 
UNIV_INLINE ulint lock_rec_get_gap (const lock_t *lock)
 Gets the gap flag of a record lock. More...
 
UNIV_INLINE ulint lock_rec_get_rec_not_gap (const lock_t *lock)
 Gets the LOCK_REC_NOT_GAP flag of a record lock. More...
 
UNIV_INLINE ulint lock_rec_get_insert_intention (const lock_t *lock)
 Gets the waiting insert flag of a record lock. More...
 
UNIV_INLINE bool lock_rec_has_to_wait (const trx_t *trx, ulint type_mode, const lock_t *lock2, bool lock_is_on_supremum)
 Checks if a lock request for a new lock has to wait for request lock2. More...
 
bool lock_has_to_wait (const lock_t *lock1, const lock_t *lock2)
 Checks if a lock request lock1 has to wait for request lock2. More...
 
ulint lock_rec_find_set_bit (const lock_t *lock)
 Looks for a set bit in a record lock bitmap. More...
 
ulint lock_rec_find_next_set_bit (const lock_t *lock, ulint heap_no)
 Looks for the next set bit in the record lock bitmap. More...
 
UNIV_INLINE byte lock_rec_reset_nth_bit (lock_t *lock, ulint i)
 Reset the nth bit of a record lock. More...
 
void lock_rec_trx_wait (lock_t *lock, ulint i, ulint type)
 Reset the nth bit of a record lock. More...
 
bool lock_rec_expl_exist_on_page (const page_id_t &page_id)
 Determines if there are explicit record locks on a page. More...
 
static void lock_rec_bitmap_reset (lock_t *lock)
 Resets the record lock bitmap to zero. More...
 
static lock_tlock_rec_copy (const lock_t *lock, mem_heap_t *heap)
 Copies a record lock to heap. More...
 
const lock_tlock_rec_get_prev (const lock_t *in_lock, ulint heap_no)
 Gets the previous record lock set on a record. More...
 
UNIV_INLINE const lock_tlock_rec_has_expl (ulint precise_mode, const buf_block_t *block, ulint heap_no, const trx_t *trx)
 Checks if a transaction has a GRANTED explicit lock on rec stronger or equal to precise_mode. More...
 
static const lock_tlock_rec_other_has_expl_req (lock_mode mode, const buf_block_t *block, bool wait, ulint heap_no, const trx_t *trx)
 Checks if some other transaction has a lock request in the queue. More...
 
static const lock_tlock_rec_other_has_conflicting (ulint mode, const buf_block_t *block, ulint heap_no, const trx_t *trx)
 Checks if some other transaction has a conflicting explicit lock request in the queue, so that we have to wait. More...
 
static trx_tlock_sec_rec_some_has_impl (const rec_t *rec, dict_index_t *index, const ulint *offsets)
 Checks if some transaction has an implicit x-lock on a record in a secondary index. More...
 
static bool lock_rec_other_trx_holds_expl (ulint precise_mode, const trx_t *trx, const rec_t *rec, const buf_block_t *block)
 Checks if some transaction, other than given trx_id, has an explicit lock on the given rec, in the given precise_mode. More...
 
ulint lock_number_of_rows_locked (const trx_lock_t *trx_lock)
 Return approximate number or record locks (bits set in the bitmap) for this transaction. More...
 
ulint lock_number_of_tables_locked (const trx_t *trx)
 Return the number of table locks for a transaction. More...
 
static void lock_rec_insert_to_waiting (hash_table_t *lock_hash, lock_t *lock, const RecID &rec_id)
 Insert lock record to the tail of the queue where the WAITING locks reside. More...
 
static void lock_rec_insert_to_granted (hash_table_t *lock_hash, lock_t *lock, const RecID &rec_id)
 Insert lock record to the head of the queue where the GRANTED locks reside. More...
 
static void locksys::add_to_trx_locks (lock_t *lock)
 Adds the lock to the list of trx's locks. More...
 
static void locksys::remove_from_trx_locks (lock_t *lock)
 Removes the lock from the list of trx's locks. More...
 
static void lock_mark_trx_for_rollback (hit_list_t &hit_list, trx_id_t hp_trx_id, trx_t *trx)
 Collect the transactions that will need to be rolled back asynchronously. More...
 
static void lock_create_wait_for_edge (trx_t *waiter, trx_t *blocker)
 Creates a new edge in wait-for graph, from waiter to blocker. More...
 
static void lock_rec_move_granted_to_front (lock_t *lock, const RecID &rec_id)
 Moves a granted lock to the front of the queue for a given record by removing it adding it to the front. More...
 
UNIV_INLINE lock_tlock_rec_find_similar_on_page (uint32_t type_mode, size_t heap_no, lock_t *lock, const trx_t *trx, bool &found_waiter_before_lock)
 Looks for a suitable type record lock struct by the same trx on the same page. More...
 
static void lock_rec_add_to_queue (ulint type_mode, const buf_block_t *block, const ulint heap_no, dict_index_t *index, trx_t *trx, const bool we_own_trx_mutex=false)
 Adds a record lock request in the record queue. More...
 
UNIV_INLINE lock_rec_req_status lock_rec_lock_fast (bool impl, ulint mode, const buf_block_t *block, ulint heap_no, dict_index_t *index, que_thr_t *thr)
 This is a fast routine for locking a record in the most common cases: there are no explicit locks on the page, or there is just one lock, owned by this transaction, and of the right type_mode. More...
 
static void lock_reuse_for_next_key_lock (const lock_t *held_lock, ulint mode, const buf_block_t *block, ulint heap_no, dict_index_t *index, trx_t *trx)
 A helper function for lock_rec_lock_slow(), which grants a Next Key Lock (either LOCK_X or LOCK_S as specified by mode) on <block,heap_no> in the index to the trx, assuming that it already has a granted held_lock, which is at least as strong as mode|LOCK_REC_NOT_GAP. More...
 
static dberr_t lock_rec_lock_slow (bool impl, select_mode sel_mode, ulint mode, const buf_block_t *block, ulint heap_no, dict_index_t *index, que_thr_t *thr)
 This is the general, and slower, routine for locking a record. More...
 
static dberr_t lock_rec_lock (bool impl, select_mode sel_mode, ulint mode, const buf_block_t *block, ulint heap_no, dict_index_t *index, que_thr_t *thr)
 Tries to lock the specified record in the mode requested. More...
 
static const lock_tlock_rec_has_to_wait_in_queue (const lock_t *wait_lock, const trx_t *blocking_trx=nullptr)
 Checks if a waiting record lock request still has to wait in a queue. More...
 
static void lock_grant (lock_t *lock)
 Grants a lock to a waiting lock request and releases the waiting transaction. More...
 
void lock_make_trx_hit_list (trx_t *hp_trx, hit_list_t &hit_list)
 Iterate over the granted locks which conflict with trx->lock.wait_lock and prepare the hit list for ASYNC Rollback. More...
 
static void lock_rec_cancel (lock_t *lock)
 Cancels a waiting record lock request and releases the waiting transaction that requested it. More...
 
static void lock_update_wait_for_edge (const lock_t *waiting_lock, const lock_t *blocking_lock)
 Given a waiting_lock, and blocking_lock which is the reason it has to wait, makes sure that the (only) edge in the wait-for graph outgoing from the waiting_lock->trx points to blocking_lock->trx. More...
 
template<typename Container >
static const lock_tlock_rec_has_to_wait_for_granted (const typename Container::value_type &wait_lock, const Container &granted, const size_t new_granted_index)
 Checks if a waiting record lock request still has to wait for granted locks. More...
 
static void lock_rec_grant_by_heap_no (lock_t *in_lock, ulint heap_no)
 Grant a lock to waiting transactions. More...
 
static const lock_tlock_has_to_wait_in_queue (const lock_t *wait_lock, const trx_t *blocking_trx)
 Checks if a waiting lock request still has to wait in a queue. More...
 
static void lock_grant_or_update_wait_for_edge (lock_t *lock)
 Given a lock, which was found in waiting queue, checks if it still has to wait in queue, and either grants it, or makes sure that the reason it has to wait is reflected in the wait-for graph. More...
 
static void lock_grant_or_update_wait_for_edge_if_waiting (lock_t *lock, const trx_t *releasing_trx)
 Given a lock, and a transaction which is releasing another lock from the same queue, makes sure that if the lock was waiting for this transaction, then it will either be granted, or another reason for waiting is reflected in the wait-for graph. More...
 
static void lock_rec_grant (lock_t *in_lock)
 Grant lock to waiting requests that no longer conflicts. More...
 
static void lock_rec_dequeue_from_page (lock_t *in_lock)
 Removes a record lock request, waiting or granted, from the queue and grants locks to other transactions in the queue if they now are entitled to a lock. More...
 
void lock_rec_discard (lock_t *in_lock)
 Removes a record lock request, waiting or granted, from the queue. More...
 
static void lock_rec_free_all_from_discard_page_low (page_id_t page_id, hash_table_t *lock_hash)
 Removes record lock objects set on an index page which is discarded. More...
 
void lock_rec_free_all_from_discard_page (const buf_block_t *block)
 Removes record lock objects set on an index page which is discarded. More...
 
static void lock_rec_reset_and_release_wait_low (hash_table_t *hash, const buf_block_t *block, ulint heap_no)
 Resets the lock bits for a single record. More...
 
static void lock_rec_reset_and_release_wait (const buf_block_t *block, ulint heap_no)
 Resets the lock bits for a single record. More...
 
void lock_on_statement_end (trx_t *trx)
 Called to inform lock-sys that a statement processing for a trx has just finished. More...
 
UNIV_INLINE void lock_protect_locks_till_statement_end (que_thr_t *thr)
 
static void lock_rec_inherit_to_gap (const buf_block_t *heir_block, const buf_block_t *block, ulint heir_heap_no, ulint heap_no)
 Makes a record to inherit the locks (except LOCK_INSERT_INTENTION type) of another record as gap type locks, but does not reset the lock bits of the other record. More...
 
static void lock_rec_inherit_to_gap_if_gap_lock (const buf_block_t *block, ulint heir_heap_no, ulint heap_no)
 Makes a record to inherit the gap locks (except LOCK_INSERT_INTENTION type) of another record as gap type locks, but does not reset the lock bits of the other record. More...
 
static void lock_rec_move_low (hash_table_t *lock_hash, const buf_block_t *receiver, const buf_block_t *donator, ulint receiver_heap_no, ulint donator_heap_no)
 Moves the locks of a record to another record and resets the lock bits of the donating record. More...
 
static void lock_move_granted_locks_to_front (UT_LIST_BASE_NODE_T(lock_t) &lock_list)
 Move all the granted locks to the front of the given lock list. More...
 
UNIV_INLINE void lock_rec_move (const buf_block_t *receiver, const buf_block_t *donator, ulint receiver_heap_no, ulint donator_heap_no)
 Moves the locks of a record to another record and resets the lock bits of the donating record. More...
 
void lock_move_reorganize_page (const buf_block_t *block, const buf_block_t *oblock)
 Updates the lock table when we have reorganized a page. More...
 
void lock_move_rec_list_end (const buf_block_t *new_block, const buf_block_t *block, const rec_t *rec)
 Moves the explicit locks on user records to another page if a record list end is moved to another page. More...
 
void lock_move_rec_list_start (const buf_block_t *new_block, const buf_block_t *block, const rec_t *rec, const rec_t *old_end)
 Moves the explicit locks on user records to another page if a record list start is moved to another page. More...
 
void lock_rtr_move_rec_list (const buf_block_t *new_block, const buf_block_t *block, rtr_rec_move_t *rec_move, ulint num_move)
 Moves the explicit locks on user records to another page if a record list start is moved to another page. More...
 
void lock_update_split_right (const buf_block_t *right_block, const buf_block_t *left_block)
 Updates the lock table when a page is split to the right. More...
 
void lock_update_merge_right (const buf_block_t *right_block, const rec_t *orig_succ, const buf_block_t *left_block)
 Updates the lock table when a page is merged to the right. More...
 
void lock_update_root_raise (const buf_block_t *block, const buf_block_t *root)
 Updates the lock table when the root page is copied to another in btr_root_raise_and_insert. More...
 
void lock_update_copy_and_discard (const buf_block_t *new_block, const buf_block_t *block)
 Updates the lock table when a page is copied to another and the original page is removed from the chain of leaf pages, except if page is the root! More...
 
void lock_update_split_left (const buf_block_t *right_block, const buf_block_t *left_block)
 Updates the lock table when a page is split to the left. More...
 
void lock_update_merge_left (const buf_block_t *left_block, const rec_t *orig_pred, const buf_block_t *right_block)
 Updates the lock table when a page is merged to the left. More...
 
void lock_rec_reset_and_inherit_gap_locks (const buf_block_t *heir_block, const buf_block_t *block, ulint heir_heap_no, ulint heap_no)
 Resets the original locks on heir and replaces them with gap type locks inherited from rec. More...
 
void lock_update_discard (const buf_block_t *heir_block, ulint heir_heap_no, const buf_block_t *block)
 Updates the lock table when a page is discarded. More...
 
void lock_update_insert (const buf_block_t *block, const rec_t *rec)
 Updates the lock table when a new user record is inserted. More...
 
void lock_update_delete (const buf_block_t *block, const rec_t *rec)
 Updates the lock table when a record is removed. More...
 
void lock_rec_store_on_page_infimum (const buf_block_t *block, const rec_t *rec)
 Stores on the page infimum record the explicit locks of another record. More...
 
void lock_rec_restore_from_page_infimum (const buf_block_t *block, const rec_t *rec, const buf_block_t *donator)
 Restores the state of explicit lock requests on a single record, where the state was stored on the infimum of the page. More...
 
UNIV_INLINE lock_tlock_table_create (dict_table_t *table, ulint type_mode, trx_t *trx)
 Creates a table lock object and adds it as the last in the lock queue of the table. More...
 
UNIV_INLINE void lock_table_pop_autoinc_locks (trx_t *trx)
 Pops autoinc lock requests from the transaction's autoinc_locks. More...
 
UNIV_INLINE void lock_table_remove_autoinc_lock (lock_t *lock, trx_t *trx)
 Removes an autoinc lock request from the transaction's autoinc_locks. More...
 
UNIV_INLINE void lock_table_remove_low (lock_t *lock)
 Removes a table lock request from the queue and the trx list of locks; this is a low-level function which does NOT check if waiting requests can now be granted. More...
 
static dberr_t lock_table_enqueue_waiting (ulint mode, dict_table_t *table, que_thr_t *thr)
 Enqueues a waiting request for a table lock which cannot be granted immediately. More...
 
UNIV_INLINE const lock_tlock_table_other_has_incompatible (const trx_t *trx, ulint wait, const dict_table_t *table, lock_mode mode)
 Checks if other transactions have an incompatible mode lock request in the lock queue. More...
 
dberr_t lock_table (ulint flags, dict_table_t *table, lock_mode mode, que_thr_t *thr)
 Locks the specified database table in the mode given. More...
 
void lock_table_ix_resurrect (dict_table_t *table, trx_t *trx)
 Creates a table IX lock object for a resurrected transaction. More...
 
static const lock_tlock_table_has_to_wait_in_queue (const lock_t *wait_lock, const trx_t *blocking_trx=nullptr)
 Checks if a waiting table lock request still has to wait in a queue. More...
 
static void lock_table_dequeue (lock_t *in_lock)
 Removes a table lock request, waiting or granted, from the queue and grants locks to other transactions in the queue, if they now are entitled to a lock. More...
 
dberr_t lock_table_for_trx (dict_table_t *table, trx_t *trx, enum lock_mode mode)
 Sets a lock on a table based on the given mode. More...
 
static void lock_rec_release (lock_t *lock, ulint heap_no)
 Grant a lock to waiting transactions. More...
 
void lock_rec_unlock (trx_t *trx, const buf_block_t *block, const rec_t *rec, lock_mode lock_mode)
 Removes a granted record lock of a transaction from the queue and grants locks to other transactions waiting in the queue if they now are entitled to a lock. More...
 
static void lock_release_gap_lock (lock_t *lock)
 Unlock the GAP Lock part of a Next Key Lock and grant it to waiters (if any) More...
 
static void lock_release_read_lock (lock_t *lock, bool only_gap)
 Used to release a lock during PREPARE. More...
 
template<typename S , typename F >
static bool locksys::try_relatch_trx_and_shard_and_do (const trx_t *const trx, const S &shard, 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...
 
template<typename F >
static bool locksys::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 locksys::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 void lock_trx_release_read_locks_in_x_mode (trx_t *trx, bool only_gap)
 Release read locks of a transacion latching the whole lock-sys in exclusive mode, which is a bit too expensive to do by default. More...
 
void lock_trx_release_read_locks (trx_t *trx, bool only_gap)
 Release read locks of a transaction. More...
 
static void lock_release (trx_t *trx)
 Releases transaction locks, and releases possible other transactions waiting because of these locks. More...
 
static void lock_trx_table_locks_remove (const lock_t *lock_to_remove)
 Removes lock_to_remove from lock_to_remove->trx->lock.table_locks. More...
 
static void lock_remove_all_on_table_for_trx (dict_table_t *table, trx_t *trx, ibool remove_also_table_sx_locks)
 Removes locks of a transaction on a table to be dropped. More...
 
static ulint lock_remove_recovered_trx_record_locks (dict_table_t *table)
 Remove any explicit record locks held by recovering transactions on the table. More...
 
void lock_remove_all_on_table (dict_table_t *table, ibool remove_also_table_sx_locks)
 Removes locks on a table to be dropped. More...
 
static void lock_table_print (FILE *file, const lock_t *lock)
 Prints info of a table lock. More...
 
static void lock_rec_print (FILE *file, const lock_t *lock)
 Prints info of a record lock. More...
 
static ulint lock_get_n_rec_locks (void)
 Calculates the number of record lock structs in the record lock hash table. More...
 
void lock_print_info_summary (FILE *file)
 Prints info of locks for all transactions. More...
 
void lock_trx_print_wait_and_mvcc_state (FILE *file, const trx_t *trx)
 Prints transaction lock wait and MVCC state. More...
 
static bool lock_rec_fetch_page (const lock_t *lock)
 Reads the page containing the record protected by the given lock. More...
 
static bool lock_trx_print_locks (FILE *file, const trx_t *trx, TrxLockIterator &iter, bool load_block)
 Prints info of locks for a transaction. More...
 
void lock_print_info_all_transactions (FILE *file)
 Prints info of locks for each transaction. More...
 
static bool lock_trx_table_locks_find (const trx_t *trx, const lock_t *find_lock)
 Check if the lock exists in the trx_t::trx_lock_t::table_locks vector. More...
 
static bool lock_table_queue_validate (const dict_table_t *table)
 Validates the lock queue on a table. More...
 
static void locksys::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 locksys::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 locksys::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...
 
static bool lock_validate_table_locks (const trx_ut_list_t *trx_list)
 Validates the table locks. More...
 
static void lock_rec_block_validate (const page_id_t &page_id)
 Validate a record lock's block. More...
 
bool lock_validate ()
 Validates the lock system. More...
 
dberr_t lock_rec_insert_check_and_lock (ulint flags, const rec_t *rec, buf_block_t *block, dict_index_t *index, que_thr_t *thr, mtr_t *mtr, ibool *inherit)
 Checks if locks of other transactions prevent an immediate insert of a record. More...
 
static void lock_rec_convert_impl_to_expl_for_trx (const buf_block_t *block, const rec_t *rec, dict_index_t *index, const ulint *offsets, trx_t *trx, ulint heap_no)
 Creates an explicit record lock for a running transaction that currently only has an implicit lock on the record. More...
 
static void lock_rec_convert_impl_to_expl (const buf_block_t *block, const rec_t *rec, dict_index_t *index, const ulint *offsets)
 If a transaction has an implicit x-lock on a record, but no explicit x-lock set on the record, sets one for it. More...
 
void lock_rec_convert_active_impl_to_expl (const buf_block_t *block, const rec_t *rec, dict_index_t *index, const ulint *offsets, trx_t *trx, ulint heap_no)
 This function is kind of wrapper to lock_rec_convert_impl_to_expl_for_trx() function with functionailty added to facilitate lock conversion from implicit to explicit for partial rollback cases. More...
 
dberr_t lock_clust_rec_modify_check_and_lock (ulint flags, const buf_block_t *block, const rec_t *rec, dict_index_t *index, const ulint *offsets, que_thr_t *thr)
 Checks if locks of other transactions prevent an immediate modify (update, delete mark, or delete unmark) of a clustered index record. More...
 
dberr_t lock_sec_rec_modify_check_and_lock (ulint flags, buf_block_t *block, const rec_t *rec, dict_index_t *index, que_thr_t *thr, mtr_t *mtr)
 Checks if locks of other transactions prevent an immediate modify (delete mark or delete unmark) of a secondary index record. More...
 
dberr_t lock_sec_rec_read_check_and_lock (const lock_duration_t duration, const buf_block_t *block, const rec_t *rec, dict_index_t *index, const ulint *offsets, const select_mode sel_mode, const lock_mode mode, const ulint gap_mode, que_thr_t *thr)
 Like lock_clust_rec_read_check_and_lock(), but reads a secondary index record. More...
 
dberr_t lock_clust_rec_read_check_and_lock (const lock_duration_t duration, const buf_block_t *block, const rec_t *rec, dict_index_t *index, const ulint *offsets, const select_mode sel_mode, const lock_mode mode, const ulint gap_mode, que_thr_t *thr)
 Checks if locks of other transactions prevent an immediate read, or passing over by a read cursor, of a clustered index record. More...
 
dberr_t lock_clust_rec_read_check_and_lock_alt (const buf_block_t *block, const rec_t *rec, dict_index_t *index, lock_mode mode, ulint gap_mode, que_thr_t *thr)
 Checks if locks of other transactions prevent an immediate read, or passing over by a read cursor, of a clustered index record. More...
 
UNIV_INLINE void lock_release_autoinc_last_lock (trx_t *trx)
 Release the last lock from the transaction's autoinc locks. More...
 
static bool lock_trx_holds_autoinc_locks (const trx_t *trx)
 Check if a transaction holds any autoinc locks. More...
 
static void lock_release_autoinc_locks (trx_t *trx)
 Release all the transaction's autoinc locks. More...
 
uint32_t lock_get_type (const lock_t *lock)
 Gets the type of a lock. More...
 
uint64_t lock_get_trx_immutable_id (const lock_t *lock)
 Gets the immutable id of the transaction owning a lock. More...
 
trx_id_t lock_get_trx_id (const lock_t *lock)
 Gets the id of the transaction owning a lock. More...
 
uint64_t lock_get_immutable_id (const lock_t *lock)
 Gets the immutable id of this lock. More...
 
void lock_get_psi_event (const lock_t *lock, ulonglong *thread_id, ulonglong *event_id)
 Get the performance schema event (thread_id, event_id) that created the lock. More...
 
const lock_tlock_get_first_trx_locks (const trx_lock_t *trx_lock)
 Get the first lock of a trx lock list. More...
 
const lock_tlock_get_next_trx_locks (const lock_t *lock)
 Get the next lock of a trx lock list. More...
 
const char * lock_get_mode_str (const lock_t *lock)
 Gets the mode of a lock in a human readable string. More...
 
const char * lock_get_type_str (const lock_t *lock)
 Gets the type of a lock in a human readable string. More...
 
UNIV_INLINE dict_table_tlock_get_table (const lock_t *lock)
 Gets the table on which the lock is. More...
 
table_id_t lock_get_table_id (const lock_t *lock)
 Gets the id of the table on which the lock is. More...
 
const table_name_tlock_get_table_name (const lock_t *lock)
 Determine which table a lock is associated with. More...
 
const dict_index_tlock_rec_get_index (const lock_t *lock)
 For a record lock, gets the index on which the lock is. More...
 
const char * lock_rec_get_index_name (const lock_t *lock)
 For a record lock, gets the name of the index on which the lock is. More...
 
page_id_t lock_rec_get_page_id (const lock_t *lock)
 For a record lock, gets the tablespace number and page number on which the lock is. More...
 
void lock_cancel_waiting_and_release (lock_t *lock)
 Cancels a waiting lock request and releases possible other transactions waiting behind it. More...
 
void lock_unlock_table_autoinc (trx_t *trx)
 Unlocks AUTO_INC type locks that were possibly reserved by a trx. More...
 
void lock_trx_release_locks (trx_t *trx)
 Releases a transaction's locks, and releases possible other transactions waiting because of these locks. More...
 
dberr_t lock_trx_handle_wait (trx_t *trx)
 Check whether the transaction has already been rolled back because it was selected as a deadlock victim, or if it has to wait then cancel the wait lock. More...
 
static const lock_tlock_table_locks_lookup (const dict_table_t *table, const trx_ut_list_t *trx_list)
 Do an exhaustive check for any locks (table or rec) against the table. More...
 
bool lock_table_has_locks (const dict_table_t *table)
 Check if there are any locks (table or rec) against table. More...
 
void lock_table_lock_list_init (table_lock_list_t *lock_list)
 Initialise the table lock list. More...
 
void lock_trx_lock_list_init (trx_lock_list_t *lock_list)
 Initialise the trx lock list. More...
 
void lock_set_timeout_event ()
 Set the lock system timeout event. More...
 
bool lock_trx_has_rec_x_lock (que_thr_t *thr, const dict_table_t *table, const buf_block_t *block, ulint heap_no)
 Check if the transaction holds an exclusive lock on a record. More...
 
void lock_trx_alloc_locks (trx_t *trx)
 Allocate cached locks for the transaction. More...
 
void lock_notify_about_deadlock (const ut::vector< const trx_t *> &trxs_on_cycle, const trx_t *victim_trx)
 Handles writing the information about found deadlock to the log files and caches it for future lock_latest_err_file() calls (for example used by SHOW ENGINE INNODB STATUS) More...
 

Variables

bool innobase_deadlock_detect = true
 
static const ulint REC_LOCK_CACHE = 8
 Total number of cached record locks. More...
 
static const ulint REC_LOCK_SIZE = sizeof(ib_lock_t) + 256
 Maximum record lock size in bytes. More...
 
static const ulint TABLE_LOCK_CACHE = 8
 Total number of cached table locks. More...
 
static const ulint TABLE_LOCK_SIZE = sizeof(ib_lock_t)
 Size in bytes, of the table lock instance. More...
 
static const std::map< uint, const char * > lock_constant_names
 Used by lock_get_mode_str to build a lock mode description. More...
 
static std::unordered_map< uint, const char * > lock_cached_lock_mode_names
 Used by lock_get_mode_str to cache results. More...
 
lock_sys_tlock_sys = nullptr
 The lock system. More...
 
static bool lock_deadlock_found = false
 We store info on the latest deadlock error to this buffer. More...
 
static FILE * lock_latest_err_file
 Only created if !srv_read_only_mode. More...
 

Detailed Description

The transaction lock system.

Created 5/7/1996 Heikki Tuuri

Macro Definition Documentation

◆ IS_LOCK_S_OR_X

#define IS_LOCK_S_OR_X (   lock)    (lock_get_mode(lock) == LOCK_S || lock_get_mode(lock) == LOCK_X)

◆ LOCK_MODULE_IMPLEMENTATION

#define LOCK_MODULE_IMPLEMENTATION

◆ PRINT_NUM_OF_LOCK_STRUCTS

#define PRINT_NUM_OF_LOCK_STRUCTS

Typedef Documentation

◆ Locks

template<typename T >
using Locks = std::vector<T, mem_heap_allocator<T> >

Function Documentation

◆ lock_cancel_waiting_and_release()

void lock_cancel_waiting_and_release ( lock_t lock)

Cancels a waiting lock request and releases possible other transactions waiting behind it.

Parameters
[in,out]lockWaiting lock request

◆ lock_check_trx_id_sanity()

bool lock_check_trx_id_sanity ( trx_id_t  trx_id,
const rec_t rec,
const dict_index_t index,
const ulint *  offsets 
)

Checks that a transaction id is sensible, i.e., not in the future.

Returns
true if ok
Parameters
trx_idin: trx id
recin: user record
indexin: index
offsetsin: rec_get_offsets(rec, index)

◆ lock_clust_rec_cons_read_sees()

bool lock_clust_rec_cons_read_sees ( const rec_t rec,
dict_index_t index,
const ulint *  offsets,
ReadView view 
)

Checks that a record is seen in a consistent read.

Returns
true if sees, or false if an earlier version of the record should be retrieved
Parameters
recin: user record which should be read or passed over by a read cursor
indexin: clustered index
offsetsin: rec_get_offsets(rec, index)
viewin: consistent read view

◆ lock_clust_rec_modify_check_and_lock()

dberr_t lock_clust_rec_modify_check_and_lock ( ulint  flags,
const buf_block_t block,
const rec_t rec,
dict_index_t index,
const ulint *  offsets,
que_thr_t thr 
)

Checks if locks of other transactions prevent an immediate modify (update, delete mark, or delete unmark) of a clustered index record.

If they do, first tests if the query thread should anyway be suspended for some reason; if not, then puts the transaction and the query thread to the lock wait state and inserts a waiting request for a record x-lock to the lock queue.

Returns
DB_SUCCESS, DB_LOCK_WAIT, or DB_DEADLOCK
Parameters
flagsin: if BTR_NO_LOCKING_FLAG bit is set, does nothing
blockin: buffer block of rec
recin: record which should be modified
indexin: clustered index
offsetsin: rec_get_offsets(rec, index)
thrin: query thread

◆ lock_clust_rec_read_check_and_lock()

dberr_t lock_clust_rec_read_check_and_lock ( lock_duration_t  duration,
const buf_block_t block,
const rec_t rec,
dict_index_t index,
const ulint *  offsets,
select_mode  sel_mode,
lock_mode  mode,
ulint  gap_mode,
que_thr_t thr 
)

Checks if locks of other transactions prevent an immediate read, or passing over by a read cursor, of a clustered index record.

If they do, first tests if the query thread should anyway be suspended for some reason; if not, then puts the transaction and the query thread to the lock wait state and inserts a waiting request for a record lock to the lock queue. Sets the requested mode lock on the record.

Parameters
[in]durationIf equal to AT_LEAST_STATEMENT, then makes sure that the lock will be kept around and inherited for at least the duration of current statement. If equal to REGULAR the life-cycle of the lock will depend on isolation level rules.
[in]blockbuffer block of rec
[in]recuser record or page supremum record which should be read or passed over by a read cursor
[in]indexsecondary index
[in]offsetsrec_get_offsets(rec, index)
[in]sel_modeselect mode: SELECT_ORDINARY, SELECT_SKIP_LOKCED, or SELECT_NO_WAIT
[in]modemode of the lock which the read cursor should set on records: LOCK_S or LOCK_X; the latter is possible in SELECT FOR UPDATE
[in]gap_modeLOCK_ORDINARY, LOCK_GAP, or LOCK_REC_NOT_GAP
[in,out]thrquery thread
Returns
DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK, DB_SKIP_LOCKED, or DB_LOCK_NOWAIT

◆ lock_clust_rec_read_check_and_lock_alt()

dberr_t lock_clust_rec_read_check_and_lock_alt ( const buf_block_t block,
const rec_t rec,
dict_index_t index,
lock_mode  mode,
ulint  gap_mode,
que_thr_t thr 
)

Checks if locks of other transactions prevent an immediate read, or passing over by a read cursor, of a clustered index record.

If they do, first tests if the query thread should anyway be suspended for some reason; if not, then puts the transaction and the query thread to the lock wait state and inserts a waiting request for a record lock to the lock queue. Sets the requested mode lock on the record. This is an alternative version of lock_clust_rec_read_check_and_lock() that does not require the parameter "offsets".

Returns
DB_SUCCESS, DB_LOCK_WAIT, or DB_DEADLOCK
Parameters
blockin: buffer block of rec
recin: user record or page supremum record which should be read or passed over by a read cursor
indexin: clustered index
modein: mode of the lock which the read cursor should set on records: LOCK_S or LOCK_X; the latter is possible in SELECT FOR UPDATE
gap_modein: LOCK_ORDINARY, LOCK_GAP, or LOCK_REC_NOT_GAP
thrin: query thread

◆ lock_create_wait_for_edge()

static void lock_create_wait_for_edge ( trx_t waiter,
trx_t blocker 
)
static

Creates a new edge in wait-for graph, from waiter to blocker.

Parameters
[in]waiterThe transaction that has to wait for blocker
[in]blockerThe transaction which causes waiter to wait

◆ lock_get_first_trx_locks()

const lock_t* lock_get_first_trx_locks ( const trx_lock_t trx_lock)

Get the first lock of a trx lock list.

Parameters
[in]trx_lockthe trx lock
Returns
The first lock

◆ lock_get_immutable_id()

uint64_t lock_get_immutable_id ( const lock_t lock)

Gets the immutable id of this lock.

Parameters
[in]lockThe lock we are interested in
Returns
The lock's immutable id

◆ lock_get_mode_str()

const char* lock_get_mode_str ( const lock_t lock)

Gets the mode of a lock in a human readable string.

The string should not be free()'d or modified. This functions is a bit complex for following reasons:

  • the way it is used in performance schema requires that the memory pointed by the return value is accessible for a long time
  • the caller never frees the memory
  • so, we need to maintain a pool of these strings or use string literals
  • there are many possible combinations of flags and thus it is impractical to maintain the list of all possible literals and if/else logic
  • moreover, sometimes performance_schema.data_locks is used precisely to investigate some unexpected situation, thus limiting output of this function only to expected combinations of flags might be misleading
    Returns
    lock mode
Parameters
lockin: lock

◆ lock_get_n_rec_locks()

static ulint lock_get_n_rec_locks ( void  )
static

Calculates the number of record lock structs in the record lock hash table.

Returns
number of record locks

◆ lock_get_next_trx_locks()

const lock_t* lock_get_next_trx_locks ( const lock_t lock)

Get the next lock of a trx lock list.

Parameters
[in]lockthe current lock
Returns
The next lock

◆ lock_get_psi_event()

void lock_get_psi_event ( const lock_t lock,
ulonglong thread_id,
ulonglong event_id 
)

Get the performance schema event (thread_id, event_id) that created the lock.

Parameters
[in]lockLock
[out]thread_idThread ID that created the lock
[out]event_idEvent ID that created the lock

◆ lock_get_size()

ulint lock_get_size ( void  )

Gets the size of a lock struct.

Returns
size in bytes

◆ lock_get_table()

UNIV_INLINE dict_table_t* lock_get_table ( const lock_t lock)

Gets the table on which the lock is.

Returns
table
Parameters
lockin: lock

◆ lock_get_table_id()

table_id_t lock_get_table_id ( const lock_t lock)

Gets the id of the table on which the lock is.

Returns
id of the table
Parameters
lockin: lock

◆ lock_get_table_name()

const table_name_t& lock_get_table_name ( const lock_t lock)

Determine which table a lock is associated with.

Parameters
[in]lockthe lock
Returns
name of the table

◆ lock_get_trx_id()

trx_id_t lock_get_trx_id ( const lock_t lock)

Gets the id of the transaction owning a lock.

Parameters
[in]lockA lock of the transaction we are interested in
Returns
the transaction's id

◆ lock_get_trx_immutable_id()

uint64_t lock_get_trx_immutable_id ( const lock_t lock)

Gets the immutable id of the transaction owning a lock.

Parameters
[in]lockA lock of the transaction we are interested in
Returns
the transaction's immutable id

◆ lock_get_type()

uint32_t lock_get_type ( const lock_t lock)

Gets the type of a lock.

Non-inline version for using outside of the lock module.

Returns
LOCK_TABLE or LOCK_REC
Parameters
lockin: lock

◆ lock_get_type_str()

const char* lock_get_type_str ( const lock_t lock)

Gets the type of a lock in a human readable string.

The string should not be free()'d or modified.

Returns
lock type
Parameters
lockin: lock

◆ lock_grant()

static void lock_grant ( lock_t lock)
static

Grants a lock to a waiting lock request and releases the waiting transaction.

The caller must hold lock_sys latch for the shard containing the lock, but not the lock->trx->mutex.

Parameters
[in,out]lockwaiting lock request

◆ lock_grant_or_update_wait_for_edge()

static void lock_grant_or_update_wait_for_edge ( lock_t lock)
static

Given a lock, which was found in waiting queue, checks if it still has to wait in queue, and either grants it, or makes sure that the reason it has to wait is reflected in the wait-for graph.

Parameters
[in]lockA lock in WAITING state, which perhaps can be granted now

◆ lock_grant_or_update_wait_for_edge_if_waiting()

static void lock_grant_or_update_wait_for_edge_if_waiting ( lock_t lock,
const trx_t releasing_trx 
)
static

Given a lock, and a transaction which is releasing another lock from the same queue, makes sure that if the lock was waiting for this transaction, then it will either be granted, or another reason for waiting is reflected in the wait-for graph.

◆ lock_has_to_wait()

bool lock_has_to_wait ( const lock_t lock1,
const lock_t lock2 
)

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

Returns
true if lock1 has to wait for lock2 to be removed
Parameters
lock1in: waiting lock
lock2in: another 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

◆ lock_has_to_wait_in_queue()

static const lock_t * lock_has_to_wait_in_queue ( const lock_t wait_lock,
const trx_t blocking_trx 
)
static

Checks if a waiting lock request still has to wait in a queue.

Parameters
[in]wait_lockWaiting lock
[in]blocking_trxIf not nullptr, it restricts the search to only the locks held by the blocking_trx, which is useful in case when there might be multiple reasons for waiting in queue, but we need to report the specific one. Useful when reporting a deadlock cycle.
Returns
The conflicting lock which is the reason wait_lock has to wait or nullptr if it can be granted now

◆ lock_make_trx_hit_list()

void lock_make_trx_hit_list ( trx_t trx,
hit_list_t hit_list 
)

Iterate over the granted locks which conflict with trx->lock.wait_lock and prepare the hit list for ASYNC Rollback.

If the transaction is waiting for some other lock then wake up with deadlock error. Currently we don't mark following transactions for ASYNC Rollback.

  1. Read only transactions
  2. Background transactions
  3. Other High priority transactions
    Parameters
    [in]trxHigh Priority transaction
    [in,out]hit_listList of transactions which need to be rolled back

◆ lock_mark_trx_for_rollback()

static void lock_mark_trx_for_rollback ( hit_list_t hit_list,
trx_id_t  hp_trx_id,
trx_t trx 
)
static

Collect the transactions that will need to be rolled back asynchronously.

Parameters
[in,out]hit_listThe list of transactions to be rolled back, to which the trx should be appended.
[in]hp_trx_idThe id of the blocked High Priority Transaction
[in,out]trxThe blocking transaction to be rolled back

◆ lock_move_granted_locks_to_front()

static void lock_move_granted_locks_to_front ( UT_LIST_BASE_NODE_T(lock_t) &  lock_list)
static

Move all the granted locks to the front of the given lock list.

All the waiting locks will be at the end of the list.

Parameters
[in,out]lock_listthe given lock list.

◆ lock_move_rec_list_end()

void lock_move_rec_list_end ( const buf_block_t new_block,
const buf_block_t block,
const rec_t rec 
)

Moves the explicit locks on user records to another page if a record list end is moved to another page.

Parameters
new_blockin: index page to move to
blockin: index page
recin: record on page: this is the first record moved

◆ lock_move_rec_list_start()

void lock_move_rec_list_start ( const buf_block_t new_block,
const buf_block_t block,
const rec_t rec,
const rec_t old_end 
)

Moves the explicit locks on user records to another page if a record list start is moved to another page.

Parameters
new_blockin: index page to move to
blockin: index page
recin: record on page: this is the first record NOT copied
old_endin: old previous-to-last record on new_page before the records were copied

◆ lock_move_reorganize_page()

void lock_move_reorganize_page ( const buf_block_t block,
const buf_block_t oblock 
)

Updates the lock table when we have reorganized a page.

NOTE: we copy also the locks set on the infimum of the page; the infimum may carry locks if an update of a record is occurring on the page, and its locks were temporarily stored on the infimum.

Parameters
blockin: old index page, now reorganized
oblockin: copy of the old, not reorganized page

◆ lock_notify_about_deadlock()

void lock_notify_about_deadlock ( const ut::vector< const trx_t *> &  trxs_on_cycle,
const trx_t victim_trx 
)

Handles writing the information about found deadlock to the log files and caches it for future lock_latest_err_file() calls (for example used by SHOW ENGINE INNODB STATUS)

Parameters
[in]trxs_on_cycletrxs causing deadlock, i-th waits for i+1-th
[in]victim_trxthe trx from trx_on_cycle which will be rolled back

◆ lock_number_of_rows_locked()

ulint lock_number_of_rows_locked ( const trx_lock_t trx_lock)

Return approximate number or record locks (bits set in the bitmap) for this transaction.

Since delete-marked records may be removed, the record count will not be precise. The caller must be holding exclusive global lock_sys latch.

Parameters
[in]trx_locktransaction locks

◆ lock_number_of_tables_locked()

ulint lock_number_of_tables_locked ( const trx_t trx)

Return the number of table locks for a transaction.

The caller must be holding trx->mutex.

Parameters
[in]trxthe transaction for which we want the number of table locks

◆ lock_on_statement_end()

void lock_on_statement_end ( trx_t trx)

Called to inform lock-sys that a statement processing for a trx has just finished.

Parameters
[in]trxtransaction which has finished processing a statement

◆ lock_print_info_all_transactions()

void lock_print_info_all_transactions ( FILE *  file)

Prints info of locks for each transaction.

This function assumes that the caller holds the exclusive global latch and more importantly it may release and reacquire it on behalf of the caller. (This should be fixed in the future).

Parameters
[in,out]filethe file where to print

◆ lock_print_info_summary()

void lock_print_info_summary ( FILE *  file)

Prints info of locks for all transactions.

Parameters
[in]filefile where to print

◆ lock_protect_locks_till_statement_end()

UNIV_INLINE void lock_protect_locks_till_statement_end ( que_thr_t thr)

◆ lock_rec_add_to_queue()

static void lock_rec_add_to_queue ( ulint  type_mode,
const buf_block_t block,
const ulint  heap_no,
dict_index_t index,
trx_t trx,
const bool  we_own_trx_mutex = false 
)
static

Adds a record lock request in the record queue.

The request is normally added as the last in the queue, but if the request to be added is not a waiting request, we can reuse a suitable record lock object already existing on the same page, just setting the appropriate bit in its bitmap. This is a low-level function which does NOT check for deadlocks or lock compatibility!

Parameters
[in]type_modelock mode, wait, gap etc. flags; type is ignored and replaced by LOCK_REC
[in]blockbuffer block containing the record
[in]heap_noheap number of the record
[in]indexindex of record
[in,out]trxtransaction
[in]we_own_trx_mutextrue iff the caller own trx->mutex (optional). Defaults to false.

◆ lock_rec_bitmap_reset()

static void lock_rec_bitmap_reset ( lock_t lock)
static

Resets the record lock bitmap to zero.

NOTE: does not touch the wait_lock pointer in the transaction! This function is used in lock object creation and resetting.

Parameters
lockin: record lock

◆ lock_rec_block_validate()

static void lock_rec_block_validate ( const page_id_t page_id)
static

Validate a record lock's block.

◆ lock_rec_cancel()

static void lock_rec_cancel ( lock_t lock)
static

Cancels a waiting record lock request and releases the waiting transaction that requested it.

NOTE: does NOT check if waiting lock requests behind this one can now be granted!

Parameters
lockin: waiting record lock request

◆ lock_rec_convert_active_impl_to_expl()

void lock_rec_convert_active_impl_to_expl ( const buf_block_t block,
const rec_t rec,
dict_index_t index,
const ulint *  offsets,
trx_t trx,
ulint  heap_no 
)

This function is kind of wrapper to lock_rec_convert_impl_to_expl_for_trx() function with functionailty added to facilitate lock conversion from implicit to explicit for partial rollback cases.

Parameters
[in]blockbuffer block of rec
[in]recuser record on page
[in]indexindex of record
[in]offsetsrec_get_offsets(rec, index)
[in,out]trxactive transaction
[in]heap_norec heap number to lock

◆ lock_rec_convert_impl_to_expl()

static void lock_rec_convert_impl_to_expl ( const buf_block_t block,
const rec_t rec,
dict_index_t index,
const ulint *  offsets 
)
static

If a transaction has an implicit x-lock on a record, but no explicit x-lock set on the record, sets one for it.

Parameters
[in]blockbuffer block of rec
[in]recuser record on page
[in]indexindex of record
[in]offsetsrec_get_offsets(rec, index)

◆ lock_rec_convert_impl_to_expl_for_trx()

static void lock_rec_convert_impl_to_expl_for_trx ( const buf_block_t block,
const rec_t rec,
dict_index_t index,
const ulint *  offsets,
trx_t trx,
ulint  heap_no 
)
static

Creates an explicit record lock for a running transaction that currently only has an implicit lock on the record.

The transaction instance must have a reference count > 0 so that it can't be committed and freed before this function has completed.

Parameters
blockin: buffer block of rec
recin: user record on page
indexin: index of record
offsetsin: rec_get_offsets(rec, index)
trxin/out: active transaction
heap_noin: rec heap number to lock

◆ lock_rec_copy()

static lock_t* lock_rec_copy ( const lock_t lock,
mem_heap_t heap 
)
static

Copies a record lock to heap.

Returns
copy of lock
Parameters
lockin: record lock
heapin: memory heap

◆ lock_rec_dequeue_from_page()

static void lock_rec_dequeue_from_page ( lock_t in_lock)
static

Removes a record lock request, waiting or granted, from the queue and grants locks to other transactions in the queue if they now are entitled to a lock.

NOTE: all record locks contained in in_lock are removed.

Parameters
[in,out]in_lockrecord lock object: all record locks which are contained in this lock object are removed; transactions waiting behind will get their lock requests granted, if they are now qualified to it

◆ lock_rec_discard()

void lock_rec_discard ( lock_t in_lock)

Removes a record lock request, waiting or granted, from the queue.

Parameters
[in]in_lockrecord lock object: all record locks which are contained in this lock object are removed

◆ lock_rec_expl_exist_on_page()

bool lock_rec_expl_exist_on_page ( const page_id_t page_id)

Determines if there are explicit record locks on a page.

Parameters
[in]page_idspace id and page number
Returns
true iff an explicit record lock on the page exists

◆ lock_rec_fetch_page()

static bool lock_rec_fetch_page ( const lock_t lock)
static

Reads the page containing the record protected by the given lock.

This function will temporarily release the exclusive global latch and the trx_sys_t::mutex if the page was read from disk.

Parameters
[in]lockthe record lock
Returns
true if a page was successfully read from the tablespace

◆ lock_rec_find_next_set_bit()

ulint lock_rec_find_next_set_bit ( const lock_t lock,
ulint  heap_no 
)

Looks for the next set bit in the record lock bitmap.

Parameters
[in]lockrecord lock with at least one bit set
[in]heap_nocurrent set bit
Returns
The next bit index == heap number following heap_no, or ULINT_UNDEFINED if none found

◆ lock_rec_find_set_bit()

ulint lock_rec_find_set_bit ( const lock_t lock)

Looks for a set bit in a record lock bitmap.

Returns ULINT_UNDEFINED, if none found.

Returns
bit index == heap number of the record, or ULINT_UNDEFINED if none found
Parameters
lockin: record lock with at least one bit set

◆ lock_rec_find_similar_on_page()

UNIV_INLINE lock_t* lock_rec_find_similar_on_page ( uint32_t  type_mode,
size_t  heap_no,
lock_t lock,
const trx_t trx,
bool found_waiter_before_lock 
)

Looks for a suitable type record lock struct by the same trx on the same page.

This can be used to save space when a new record lock should be set on a page: no new struct is needed, if a suitable old is found.

Parameters
[in]type_modelock type_mode field
[in]heap_noheap number of the record we plan to use. The lock struct we search for needs to have a bitmap at least as large.
[in]locklock_rec_get_first_on_page()
[in]trxtransaction
[out]found_waiter_before_locktrue iff there is a waiting lock before the returned lock
Returns
lock or nullptr if there is no lock we could reuse

◆ lock_rec_free_all_from_discard_page()

void lock_rec_free_all_from_discard_page ( const buf_block_t block)

Removes record lock objects set on an index page which is discarded.

This function does not move locks, or check for waiting locks, therefore the lock bitmaps must already be reset when this function is called.

Parameters
blockin: page to be discarded

◆ lock_rec_free_all_from_discard_page_low()

static void lock_rec_free_all_from_discard_page_low ( page_id_t  page_id,
hash_table_t lock_hash 
)
static

Removes record lock objects set on an index page which is discarded.

This function does not move locks, or check for waiting locks, therefore the lock bitmaps must already be reset when this function is called.

◆ lock_rec_get_gap()

UNIV_INLINE ulint lock_rec_get_gap ( const lock_t lock)

Gets the gap flag of a record lock.

Returns
LOCK_GAP or 0
Parameters
lockin: record lock

◆ lock_rec_get_index()

const dict_index_t* lock_rec_get_index ( const lock_t lock)

For a record lock, gets the index on which the lock is.

Returns
index
Parameters
lockin: lock

◆ lock_rec_get_index_name()

const char* lock_rec_get_index_name ( const lock_t lock)

For a record lock, gets the name of the index on which the lock is.

The string should not be free()'d or modified.

Returns
name of the index
Parameters
lockin: lock

◆ lock_rec_get_insert_intention()

UNIV_INLINE ulint lock_rec_get_insert_intention ( const lock_t lock)

Gets the waiting insert flag of a record lock.

Returns
LOCK_INSERT_INTENTION or 0
Parameters
lockin: record lock

◆ lock_rec_get_page_id()

page_id_t lock_rec_get_page_id ( const lock_t lock)

For a record lock, gets the tablespace number and page number on which the lock is.

Returns
tablespace number in: lock

◆ lock_rec_get_prev()

const lock_t* lock_rec_get_prev ( const lock_t in_lock,
ulint  heap_no 
)

Gets the previous record lock set on a record.

Returns
previous lock on the same record, NULL if none exists
Parameters
in_lockin: record lock
heap_noin: heap number of the record

◆ lock_rec_get_rec_not_gap()

UNIV_INLINE ulint lock_rec_get_rec_not_gap ( const lock_t lock)

Gets the LOCK_REC_NOT_GAP flag of a record lock.

Returns
LOCK_REC_NOT_GAP or 0
Parameters
lockin: record lock

◆ lock_rec_grant()

static void lock_rec_grant ( lock_t in_lock)
static

Grant lock to waiting requests that no longer conflicts.

The in_lock might be modified before call to this function by clearing some flag (see for example lock_trx_release_read_locks). It also might already be removed from the hash bucket (a.k.a. waiting queue) or still reside in it. However the content of bitmap should not be changed prior to calling this function, as the bitmap will be inspected to see which heap_no at all were blocked by this in_lock, and only locks waiting for those heap_no's will be checked.

Parameters
[in,out]in_lockrecord lock object: grant all non-conflicting locks waiting behind this lock object

◆ lock_rec_grant_by_heap_no()

static void lock_rec_grant_by_heap_no ( lock_t in_lock,
ulint  heap_no 
)
static

Grant a lock to waiting transactions.

This function scans the queue of locks in which in_lock resides (or resided) paying attention only to locks on heap_no-th bit. For each waiting lock which was blocked by in_lock->trx it checks if it can be granted now. It iterates on waiting locks in order favoring high-priority transactions and then transactions of high trx->lock.schedule_weight.

Parameters
[in]in_lockLock which was released, or partially released by modifying its type/mode (see lock_trx_release_read_locks) or reseting heap_no-th bit in the bitmap (see lock_rec_release)
[in]heap_noHeap number within the page on which the lock was (or still is) held

◆ lock_rec_has_expl()

UNIV_INLINE const lock_t* lock_rec_has_expl ( ulint  precise_mode,
const buf_block_t block,
ulint  heap_no,
const trx_t trx 
)

Checks if a transaction has a GRANTED explicit lock on rec stronger or equal to precise_mode.

Parameters
[in]precise_modeLOCK_S or LOCK_X possibly ORed to LOCK_GAP or LOCK_REC_NOT_GAP, for a supremum record we regard this always a gap type request
[in]blockbuffer block containing the record
[in]heap_noheap number of the record
[in]trxtransaction
Returns
lock or NULL

◆ lock_rec_has_to_wait()

UNIV_INLINE bool lock_rec_has_to_wait ( const trx_t trx,
ulint  type_mode,
const lock_t lock2,
bool  lock_is_on_supremum 
)

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

Returns
true if new lock has to wait for lock2 to be removed
Parameters
trxin: trx of new lock
type_modein: precise 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
lock2in: another 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
lock_is_on_supremumin: true 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

◆ lock_rec_has_to_wait_for_granted()

template<typename Container >
static const lock_t* lock_rec_has_to_wait_for_granted ( const typename Container::value_type &  wait_lock,
const Container &  granted,
const size_t  new_granted_index 
)
static

Checks if a waiting record lock request still has to wait for granted locks.

Parameters
[in]wait_lockWaiting record lock
[in]grantedGranted record locks
[in]new_granted_indexStart of new granted locks
Returns
The conflicting lock which is the reason wait_lock has to wait or nullptr if it can be granted now

◆ lock_rec_has_to_wait_in_queue()

static const lock_t* lock_rec_has_to_wait_in_queue ( const lock_t wait_lock,
const trx_t blocking_trx = nullptr 
)
static

Checks if a waiting record lock request still has to wait in a queue.

Parameters
[in]wait_lockWaiting record lock
[in]blocking_trxIf not nullptr, it restricts the search to only the locks held by the blocking_trx, which is useful in case when there might be multiple reasons for waiting in queue, but we need to report the specific one. Useful when reporting a deadlock cycle. (optional)
Returns
The conflicting lock which is the reason wait_lock has to wait or nullptr if it can be granted now

◆ lock_rec_inherit_to_gap()

static void lock_rec_inherit_to_gap ( const buf_block_t heir_block,
const buf_block_t block,
ulint  heir_heap_no,
ulint  heap_no 
)
static

Makes a record to inherit the locks (except LOCK_INSERT_INTENTION type) of another record as gap type locks, but does not reset the lock bits of the other record.

Also waiting lock requests on rec are inherited as GRANTED gap locks.

Parameters
heir_blockin: block containing the record which inherits
blockin: block containing the record from which inherited; does NOT reset the locks on this record
heir_heap_noin: heap_no of the inheriting record
heap_noin: heap_no of the donating record

◆ lock_rec_inherit_to_gap_if_gap_lock()

static void lock_rec_inherit_to_gap_if_gap_lock ( const buf_block_t block,
ulint  heir_heap_no,
ulint  heap_no 
)
static

Makes a record to inherit the gap locks (except LOCK_INSERT_INTENTION type) of another record as gap type locks, but does not reset the lock bits of the other record.

Also waiting lock requests are inherited as GRANTED gap locks.

Parameters
blockin: buffer block
heir_heap_noin: heap_no of record which inherits
heap_noin: heap_no of record from which inherited; does NOT reset the locks on this record

◆ lock_rec_insert_check_and_lock()

dberr_t lock_rec_insert_check_and_lock ( ulint  flags,
const rec_t rec,
buf_block_t block,
dict_index_t index,
que_thr_t thr,
mtr_t mtr,
ibool *  inherit 
)

Checks if locks of other transactions prevent an immediate insert of a record.

If they do, first tests if the query thread should anyway be suspended for some reason; if not, then puts the transaction and the query thread to the lock wait state and inserts a waiting request for a gap x-lock to the lock queue.

Returns
DB_SUCCESS, DB_LOCK_WAIT, or DB_DEADLOCK
Parameters
flagsin: if BTR_NO_LOCKING_FLAG bit is set, does nothing
recin: record after which to insert
blockin/out: buffer block of rec
indexin: index
thrin: query thread
mtrin/out: mini-transaction
inheritout: set to true if the new inserted record maybe should inherit LOCK_GAP type locks from the successor record

◆ lock_rec_insert_to_granted()

static void lock_rec_insert_to_granted ( hash_table_t lock_hash,
lock_t lock,
const RecID rec_id 
)
static

Insert lock record to the head of the queue where the GRANTED locks reside.

Parameters
[in,out]lock_hashHash table containing the locks
[in,out]lockRecord lock instance to insert
[in]rec_idRecord being locked

◆ lock_rec_insert_to_waiting()

static void lock_rec_insert_to_waiting ( hash_table_t lock_hash,
lock_t lock,
const RecID rec_id 
)
static

Insert lock record to the tail of the queue where the WAITING locks reside.

Parameters
[in,out]lock_hashHash table containing the locks
[in,out]lockRecord lock instance to insert
[in]rec_idRecord being locked

◆ lock_rec_lock()

static dberr_t lock_rec_lock ( bool  impl,
select_mode  sel_mode,
ulint  mode,
const buf_block_t block,
ulint  heap_no,
dict_index_t index,
que_thr_t thr 
)
static

Tries to lock the specified record in the mode requested.

If not immediately possible, enqueues a waiting lock request. This is a low-level function which does NOT look at implicit locks! Checks lock compatibility within explicit locks. This function sets a normal next-key lock, or in the case of a page supremum record, a gap type lock.

Parameters
[in]implif true, no lock is set if no wait is necessary: we assume that the caller will set an implicit lock
[in]sel_modeselect mode: SELECT_ORDINARY, SELECT_SKIP_LOCKED, or SELECT_NO_WAIT
[in]modelock mode: LOCK_X or LOCK_S possibly ORed to either LOCK_GAP or LOCK_REC_NOT_GAP
[in]blockbuffer block containing the record
[in]heap_noheap number of record
[in]indexindex of record
[in,out]thrquery thread
Returns
DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK, DB_SKIP_LOCKED, or DB_LOCK_NOWAIT

◆ lock_rec_lock_fast()

UNIV_INLINE lock_rec_req_status lock_rec_lock_fast ( bool  impl,
ulint  mode,
const buf_block_t block,
ulint  heap_no,
dict_index_t index,
que_thr_t thr 
)

This is a fast routine for locking a record in the most common cases: there are no explicit locks on the page, or there is just one lock, owned by this transaction, and of the right type_mode.

This is a low-level function which does NOT look at implicit locks! Checks lock compatibility within explicit locks. This function sets a normal next-key lock, or in the case of a page supremum record, a gap type lock.

Returns
whether the locking succeeded LOCK_REC_SUCCESS, LOCK_REC_SUCCESS_CREATED, LOCK_REC_FAIL
Parameters
implin: if true, no lock is set if no wait is necessary: we assume that the caller will set an implicit lock
modein: lock mode: LOCK_X or LOCK_S possibly ORed to either LOCK_GAP or LOCK_REC_NOT_GAP
blockin: buffer block containing the record
heap_noin: heap number of record
indexin: index of record
thrin: query thread

◆ lock_rec_lock_fold()

static ulint lock_rec_lock_fold ( const lock_t lock)
static

Calculates the fold value of a lock: used in migrating the hash table.

Parameters
[in]lockrecord lock object
Returns
folded value

◆ lock_rec_lock_slow()

static dberr_t lock_rec_lock_slow ( bool  impl,
select_mode  sel_mode,
ulint  mode,
const buf_block_t block,
ulint  heap_no,
dict_index_t index,
que_thr_t thr 
)
static

This is the general, and slower, routine for locking a record.

This is a low-level function which does NOT look at implicit locks! Checks lock compatibility within explicit locks. This function sets a normal next-key lock, or in the case of a page supremum record, a gap type lock.

Parameters
[in]implif true, no lock is set if no wait is necessary: we assume that the caller will set an implicit lock
[in]sel_modeselect mode: SELECT_ORDINARY, SELECT_SKIP_LOCKED, or SELECT_NO_WAIT
[in]modelock mode: LOCK_X or LOCK_S possibly ORed to either LOCK_GAP or LOCK_REC_NOT_GAP
[in]blockbuffer block containing the record
[in]heap_noheap number of record
[in]indexindex of record
[in,out]thrquery thread
Returns
DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK, DB_SKIP_LOCKED, or DB_LOCK_NOWAIT

◆ lock_rec_move()

UNIV_INLINE void lock_rec_move ( const buf_block_t receiver,
const buf_block_t donator,
ulint  receiver_heap_no,
ulint  donator_heap_no 
)

Moves the locks of a record to another record and resets the lock bits of the donating record.

Parameters
receiverin: buffer block containing the receiving record
donatorin: buffer block containing the donating record
receiver_heap_noin: heap_no of the record which gets the locks; there must be no lock requests on it!
donator_heap_noin: heap_no of the record which gives the locks

◆ lock_rec_move_granted_to_front()

static void lock_rec_move_granted_to_front ( lock_t lock,
const RecID rec_id 
)
static

Moves a granted lock to the front of the queue for a given record by removing it adding it to the front.

As a single lock can correspond to multiple rows (and thus: queues) this function moves it to the front of whole bucket.

Parameters
[in]locka granted lock to be moved
[in]rec_idrecord id which specifies particular queue and bucket

◆ lock_rec_move_low()

static void lock_rec_move_low ( hash_table_t lock_hash,
const buf_block_t receiver,
const buf_block_t donator,
ulint  receiver_heap_no,
ulint  donator_heap_no 
)
static

Moves the locks of a record to another record and resets the lock bits of the donating record.

Parameters
lock_hashin: hash table to use
receiverin: buffer block containing the receiving record
donatorin: buffer block containing the donating record
receiver_heap_noin: heap_no of the record which gets the locks; there must be no lock requests on it!
donator_heap_noin: heap_no of the record which gives the locks

◆ lock_rec_other_has_conflicting()

static const lock_t* lock_rec_other_has_conflicting ( ulint  mode,
const buf_block_t block,
ulint  heap_no,
const trx_t trx 
)
static

Checks if some other transaction has a conflicting explicit lock request in the queue, so that we have to wait.

Returns
lock or NULL
Parameters
modein: LOCK_S or LOCK_X, possibly ORed to LOCK_GAP or LOC_REC_NOT_GAP, LOCK_INSERT_INTENTION
blockin: buffer block containing the record
heap_noin: heap number of the record
trxin: our transaction

◆ lock_rec_other_has_expl_req()

static const lock_t* lock_rec_other_has_expl_req ( lock_mode  mode,
const buf_block_t block,
bool  wait,
ulint  heap_no,
const trx_t trx 
)
static

Checks if some other transaction has a lock request in the queue.

Returns
lock or NULL
Parameters
modein: LOCK_S or LOCK_X
blockin: buffer block containing the record
waitin: whether also waiting locks are taken into account
heap_noin: heap number of the record
trxin: transaction, or NULL if requests by all transactions are taken into account

◆ lock_rec_other_trx_holds_expl()

static bool lock_rec_other_trx_holds_expl ( ulint  precise_mode,
const trx_t trx,
const rec_t rec,
const buf_block_t block 
)
static

Checks if some transaction, other than given trx_id, has an explicit lock on the given rec, in the given precise_mode.

Parameters
[in]precise_modeLOCK_S or LOCK_X possibly ORed to LOCK_GAP or LOCK_REC_NOT_GAP.
[in]trxthe trx holding implicit lock on rec
[in]recuser record
[in]blockbuffer block containing the record
Returns
true iff there's a transaction, whose id is not equal to trx_id, that has an explicit lock on the given rec, in the given precise_mode.

◆ lock_rec_print()

static void lock_rec_print ( FILE *  file,
const lock_t lock 
)
static

Prints info of a record lock.

Parameters
filein: file where to print
lockin: record type lock

◆ lock_rec_release()

static void lock_rec_release ( lock_t lock,
ulint  heap_no 
)
static

Grant a lock to waiting transactions.

Parameters
[in]lockLock that was unlocked
[in]heap_noHeap no within the page for the lock.

◆ lock_rec_reset_and_inherit_gap_locks()

void lock_rec_reset_and_inherit_gap_locks ( const buf_block_t heir_block,
const buf_block_t block,
ulint  heir_heap_no,
ulint  heap_no 
)

Resets the original locks on heir and replaces them with gap type locks inherited from rec.

Parameters
heir_blockin: block containing the record which inherits
blockin: block containing the record from which inherited; does NOT reset the locks on this record
heir_heap_noin: heap_no of the inheriting record
heap_noin: heap_no of the donating record

◆ lock_rec_reset_and_release_wait()

static void lock_rec_reset_and_release_wait ( const buf_block_t block,
ulint  heap_no 
)
static

Resets the lock bits for a single record.

Releases transactions waiting for lock requests here.

Parameters
blockin: buffer block containing the record
heap_noin: heap number of record

◆ lock_rec_reset_and_release_wait_low()

static void lock_rec_reset_and_release_wait_low ( hash_table_t hash,
const buf_block_t block,
ulint  heap_no 
)
static

Resets the lock bits for a single record.

Releases transactions waiting for lock requests here.

Parameters
hashin: hash table
blockin: buffer block containing the record
heap_noin: heap number of record

◆ lock_rec_reset_nth_bit()

UNIV_INLINE byte lock_rec_reset_nth_bit ( lock_t lock,
ulint  i 
)

Reset the nth bit of a record lock.

Parameters
[in,out]lockrecord lock
[in]iindex of the bit that will be reset
Returns
previous value of the bit

◆ lock_rec_restore_from_page_infimum()

void lock_rec_restore_from_page_infimum ( const buf_block_t block,
const rec_t rec,
const buf_block_t donator 
)

Restores the state of explicit lock requests on a single record, where the state was stored on the infimum of the page.

Parameters
blockin: buffer block containing rec
recin: record whose lock state is restored
donatorin: page (rec is not necessarily on this page) whose infimum stored the lock state; lock bits are reset on the infimum

◆ lock_rec_store_on_page_infimum()

void lock_rec_store_on_page_infimum ( const buf_block_t block,
const rec_t rec 
)

Stores on the page infimum record the explicit locks of another record.

This function is used to store the lock state of a record when it is updated and the size of the record changes in the update. The record is moved in such an update, perhaps to another page. The infimum record acts as a dummy carrier record, taking care of lock releases while the actual record is being moved.

Parameters
blockin: buffer block containing rec
recin: record whose lock state is stored on the infimum record of the same page; lock bits are reset on the record

◆ lock_rec_trx_wait()

void lock_rec_trx_wait ( lock_t lock,
ulint  i,
ulint  type 
)

Reset the nth bit of a record lock.

Parameters
[in,out]lockrecord lock
[in]iindex of the bit that will be reset
[in]typewhether the lock is in wait mode

◆ lock_rec_unlock()

void lock_rec_unlock ( trx_t trx,
const buf_block_t block,
const rec_t rec,
lock_mode  lock_mode 
)

Removes a granted record lock of a transaction from the queue and grants locks to other transactions waiting in the queue if they now are entitled to a lock.

This function is meant to be used only by row_unlock_for_mysql, and it assumes that the lock we are looking for has LOCK_REC_NOT_GAP flag.

Parameters
trxin/out: transaction that has set a record lock
blockin: buffer block containing rec
recin: record
lock_modein: LOCK_S or LOCK_X

◆ lock_rec_validate_page()

static bool lock_rec_validate_page ( const buf_block_t block)
static

Validates the record lock queues on a page.

Returns
true if ok
Parameters
blockin: buffer block

◆ lock_release()

static void lock_release ( trx_t trx)
static

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

Parameters
[in,out]trxtransaction

◆ lock_release_autoinc_last_lock()

UNIV_INLINE void lock_release_autoinc_last_lock ( trx_t trx)

Release the last lock from the transaction's autoinc locks.

Parameters
[in]trxtrx which vector of AUTOINC locks to modify

◆ lock_release_autoinc_locks()

static void lock_release_autoinc_locks ( trx_t trx)
static

Release all the transaction's autoinc locks.

Parameters
trxin/out: transaction

◆ lock_release_gap_lock()

static void lock_release_gap_lock ( lock_t lock)
static

Unlock the GAP Lock part of a Next Key Lock and grant it to waiters (if any)

Parameters
[in,out]locklock object

◆ lock_release_read_lock()

static void lock_release_read_lock ( lock_t lock,
bool  only_gap 
)
static

Used to release a lock during PREPARE.

The lock is only released if rules permit it.

Parameters
[in]lockthe lock that we consider releasing
[in]only_gaptrue if we don't want to release records, just the gaps between them

◆ lock_remove_all_on_table()

void lock_remove_all_on_table ( dict_table_t table,
ibool  remove_also_table_sx_locks 
)

Removes locks on a table to be dropped.

If remove_also_table_sx_locks is true then table-level S and X locks are also removed in addition to other table-level and record-level locks. No lock, that is going to be removed, is allowed to be a wait lock.

Parameters
tablein: table to be dropped or discarded
remove_also_table_sx_locksin: also removes table S and X locks

◆ lock_remove_all_on_table_for_trx()

static void lock_remove_all_on_table_for_trx ( dict_table_t table,
trx_t trx,
ibool  remove_also_table_sx_locks 
)
static

Removes locks of a transaction on a table to be dropped.

If remove_also_table_sx_locks is true then table-level S and X locks are also removed in addition to other table-level and record-level locks. No lock that is going to be removed is allowed to be a wait lock.

Parameters
tablein: table to be dropped
trxin: a transaction
remove_also_table_sx_locksin: also removes table S and X locks

◆ lock_remove_recovered_trx_record_locks()

static ulint lock_remove_recovered_trx_record_locks ( dict_table_t table)
static

Remove any explicit record locks held by recovering transactions on the table.

Returns
number of recovered transactions examined
Parameters
tablein: check if there are any locks held on records in this table or on the table itself

◆ lock_report_trx_id_insanity()

void lock_report_trx_id_insanity ( trx_id_t  trx_id,
const rec_t rec,
const dict_index_t index,
const ulint *  offsets,
trx_id_t  max_trx_id 
)

Reports that a transaction id is insensible, i.e., in the future.

Parameters
trx_idin: trx id
recin: user record
indexin: index
offsetsin: rec_get_offsets(rec, index)
max_trx_idin: trx_sys_get_max_trx_id()

◆ lock_reuse_for_next_key_lock()

static void lock_reuse_for_next_key_lock ( const lock_t held_lock,
ulint  mode,
const buf_block_t block,
ulint  heap_no,
dict_index_t index,
trx_t trx 
)
static

A helper function for lock_rec_lock_slow(), which grants a Next Key Lock (either LOCK_X or LOCK_S as specified by mode) on <block,heap_no> in the index to the trx, assuming that it already has a granted held_lock, which is at least as strong as mode|LOCK_REC_NOT_GAP.

It does so by either reusing the lock if it already covers the gap, or by ensuring a separate GAP Lock, which in combination with Record Lock satisfies the request.

Parameters
[in]held_locka lock granted to trx which is at least as strong as mode|LOCK_REC_NOT_GAP
[in]moderequested lock mode: LOCK_X or LOCK_S
[in]blockbuffer block containing the record to be locked
[in]heap_noheap number of the record to be locked
[in]indexindex of record to be locked
[in]trxthe transaction requesting the Next Key Lock

◆ lock_rtr_move_rec_list()

void lock_rtr_move_rec_list ( const buf_block_t new_block,
const buf_block_t block,
rtr_rec_move_t rec_move,
ulint  num_move 
)

Moves the explicit locks on user records to another page if a record list start is moved to another page.

Parameters
new_blockin: index page to move to
blockin: index page
rec_movein: recording records moved
num_movein: num of rec to move

◆ lock_sec_rec_cons_read_sees()

bool lock_sec_rec_cons_read_sees ( const rec_t rec,
const dict_index_t index,
const ReadView view 
)

Checks that a non-clustered index record is seen in a consistent read.

NOTE that a non-clustered index page contains so little information on its modifications that also in the case false, the present version of rec may be the right, but we must check this from the clustered index record.

Returns
true if certainly sees, or false if an earlier version of the clustered index record might be needed
Parameters
recin: user record which should be read or passed over by a read cursor
indexin: index
viewin: consistent read view

◆ lock_sec_rec_modify_check_and_lock()

dberr_t lock_sec_rec_modify_check_and_lock ( ulint  flags,
buf_block_t block,
const rec_t rec,
dict_index_t index,
que_thr_t thr,
mtr_t mtr 
)

Checks if locks of other transactions prevent an immediate modify (delete mark or delete unmark) of a secondary index record.

Returns
DB_SUCCESS, DB_LOCK_WAIT, or DB_DEADLOCK
Parameters
flagsin: if BTR_NO_LOCKING_FLAG bit is set, does nothing
blockin/out: buffer block of rec
recin: record which should be modified; NOTE: as this is a secondary index, we always have to modify the clustered index record first: see the comment below
indexin: secondary index
thrin: query thread (can be NULL if BTR_NO_LOCKING_FLAG)
mtrin/out: mini-transaction

◆ lock_sec_rec_read_check_and_lock()

dberr_t lock_sec_rec_read_check_and_lock ( lock_duration_t  duration,
const buf_block_t block,
const rec_t rec,
dict_index_t index,
const ulint *  offsets,
select_mode  sel_mode,
lock_mode  mode,
ulint  gap_mode,
que_thr_t thr 
)

Like lock_clust_rec_read_check_and_lock(), but reads a secondary index record.

Parameters
[in]durationIf equal to AT_LEAST_STATEMENT, then makes sure that the lock will be kept around and inherited for at least the duration of current statement. If equal to REGULAR the life-cycle of the lock will depend on isolation level rules.
[in]blockbuffer block of rec
[in]recuser record or page supremum record which should be read or passed over by a read cursor
[in]indexsecondary index
[in]offsetsrec_get_offsets(rec, index)
[in]sel_modeselect mode: SELECT_ORDINARY, SELECT_SKIP_LOKCED, or SELECT_NO_WAIT
[in]modemode of the lock which the read cursor should set on records: LOCK_S or LOCK_X; the latter is possible in SELECT FOR UPDATE
[in]gap_modeLOCK_ORDINARY, LOCK_GAP, or LOCK_REC_NOT_GAP
[in,out]thrquery thread
Returns
DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK, DB_SKIP_LOCKED, or DB_LOCK_NOWAIT

◆ lock_sec_rec_some_has_impl()

static trx_t* lock_sec_rec_some_has_impl ( const rec_t rec,
dict_index_t index,
const ulint *  offsets 
)
static

Checks if some transaction has an implicit x-lock on a record in a secondary index.

Parameters
[in]recuser record
[in]indexsecondary index
[in]offsetsrec_get_offsets(rec, index)
Returns
transaction id of the transaction which has the x-lock, or 0; NOTE that this function can return false positives but never false negatives. The caller must confirm all positive results by checking if the trx is still active.

◆ lock_set_lock_and_trx_wait()

UNIV_INLINE void lock_set_lock_and_trx_wait ( lock_t lock)

Sets the wait flag of a lock and the back pointer in trx to lock.

Parameters
[in]lockThe lock on which a transaction is waiting

◆ lock_set_timeout_event()

void lock_set_timeout_event ( )

Set the lock system timeout event.

◆ lock_sys_close()

void lock_sys_close ( void  )

Closes the lock system at database shutdown.

◆ lock_sys_create()

void lock_sys_create ( ulint  n_cells)

Creates the lock system at database start.

Parameters
n_cellsin: number of slots in lock hash table

◆ lock_sys_resize()

void lock_sys_resize ( ulint  n_cells)

Resize the lock hash tables.

Resize the lock hash table.

Parameters
[in]n_cellsnumber of slots in lock hash table

◆ lock_table()

dberr_t lock_table ( ulint  flags,
dict_table_t table,
lock_mode  mode,
que_thr_t thr 
)

Locks the specified database table in the mode given.

If the lock cannot be granted immediately, the query thread is put to wait.

Returns
DB_SUCCESS, DB_LOCK_WAIT, or DB_DEADLOCK
Parameters
flagsin: if BTR_NO_LOCKING_FLAG bit is set, does nothing
tablein/out: database table in dictionary cache
modein: lock mode
thrin: query thread

◆ lock_table_create()

UNIV_INLINE lock_t* lock_table_create ( dict_table_t table,
ulint  type_mode,
trx_t trx 
)

Creates a table lock object and adds it as the last in the lock queue of the table.

Does NOT check for deadlocks or lock compatibility.

Returns
own: new lock object
Parameters
tablein/out: database table in dictionary cache
type_modein: lock mode possibly ORed with LOCK_WAIT
trxin: trx

◆ lock_table_dequeue()

static void lock_table_dequeue ( lock_t in_lock)
static

Removes a table lock request, waiting or granted, from the queue and grants locks to other transactions in the queue, if they now are entitled to a lock.

Parameters
in_lockin/out: table lock object; transactions waiting behind will get their lock requests granted, if they are now qualified to it

◆ lock_table_enqueue_waiting()

static dberr_t lock_table_enqueue_waiting ( ulint  mode,
dict_table_t table,
que_thr_t thr 
)
static

Enqueues a waiting request for a table lock which cannot be granted immediately.

Checks for deadlocks.

Returns
DB_LOCK_WAIT or DB_DEADLOCK
Parameters
modein: lock mode this transaction is requesting
tablein/out: table
thrin: query thread

◆ lock_table_for_trx()

dberr_t lock_table_for_trx ( dict_table_t table,
trx_t trx,
enum lock_mode  mode 
)

Sets a lock on a table based on the given mode.

Parameters
[in]tabletable to lock
[in,out]trxtransaction
[in]modeLOCK_X or LOCK_S
Returns
error code or DB_SUCCESS.

◆ lock_table_has_locks()

bool lock_table_has_locks ( const dict_table_t table)

Check if there are any locks (table or rec) against table.

Returned value might be obsolete.

Parameters
[in]tablethe table
Returns
true if there were any locks held on records in this table or on the table itself at some point in time during the call

The n_rec_locks field might be modified by operation on any page shard, so we need to latch everything. Note, that the results of this function will be obsolete, as soon as we release the latch. It is called in contexts where we believe that the number of locks should either be zero or decreasing. For such scenario of usage, we might perhaps read the n_rec_locks without latch and restrict latch just to a table shard. But that would complicate the debug version of the code for no significant gain as this is not a hot path.

◆ lock_table_has_to_wait_in_queue()

static const lock_t* lock_table_has_to_wait_in_queue ( const lock_t wait_lock,
const trx_t blocking_trx = nullptr 
)
static

Checks if a waiting table lock request still has to wait in a queue.

Parameters
[in]wait_lockWaiting table lock
[in]blocking_trxIf not nullptr, it restricts the search to only the locks held by the blocking_trx, which is useful in case when there might be multiple reasons for waiting in queue, but we need to report the specific one. Useful when reporting a deadlock cycle. (optional)
Returns
The conflicting lock which is the reason wait_lock has to wait or nullptr if it can be granted now

◆ lock_table_ix_resurrect()

void lock_table_ix_resurrect ( dict_table_t table,
trx_t trx 
)

Creates a table IX lock object for a resurrected transaction.

Parameters
tablein/out: table
trxin/out: transaction

◆ lock_table_lock_list_init()

void lock_table_lock_list_init ( table_lock_list_t lock_list)

Initialise the table lock list.

Parameters
lock_listList to initialise

◆ lock_table_locks_lookup()

static const lock_t* lock_table_locks_lookup ( const dict_table_t table,
const trx_ut_list_t *  trx_list 
)
static

Do an exhaustive check for any locks (table or rec) against the table.

Returns
lock if found
Parameters
tablein: check if there are any locks held on records in this table or on the table itself
trx_listin: trx list to check

◆ lock_table_other_has_incompatible()

UNIV_INLINE const lock_t* lock_table_other_has_incompatible ( const trx_t trx,
ulint  wait,
const dict_table_t table,
lock_mode  mode 
)

Checks if other transactions have an incompatible mode lock request in the lock queue.

Returns
lock or NULL
Parameters
trxin: transaction, or NULL if all transactions should be included
waitin: LOCK_WAIT if also waiting locks are taken into account, or 0 if not
tablein: table
modein: lock mode

◆ lock_table_pop_autoinc_locks()

UNIV_INLINE void lock_table_pop_autoinc_locks ( trx_t trx)

Pops autoinc lock requests from the transaction's autoinc_locks.

We handle the case where there are gaps in the array and they need to be popped off the stack.

Parameters
trxin/out: transaction that owns the AUTOINC locks

◆ lock_table_print()

static void lock_table_print ( FILE *  file,
const lock_t lock 
)
static

Prints info of a table lock.

Parameters
filein: file where to print
lockin: table type lock

◆ lock_table_queue_validate()

static bool lock_table_queue_validate ( const dict_table_t table)
static

Validates the lock queue on a table.

Returns
true if ok
Parameters
tablein: table

◆ lock_table_remove_autoinc_lock()

UNIV_INLINE void lock_table_remove_autoinc_lock ( lock_t lock,
trx_t trx 
)

Removes an autoinc lock request from the transaction's autoinc_locks.

Parameters
lockin: table lock
trxin/out: transaction that owns the lock

◆ lock_table_remove_low()

UNIV_INLINE void lock_table_remove_low ( lock_t lock)

Removes a table lock request from the queue and the trx list of locks; this is a low-level function which does NOT check if waiting requests can now be granted.

Parameters
lockin/out: table lock

◆ lock_trx_alloc_locks()

void lock_trx_alloc_locks ( trx_t trx)

Allocate cached locks for the transaction.

Parameters
trxallocate cached record locks for this transaction

◆ lock_trx_handle_wait()

dberr_t lock_trx_handle_wait ( trx_t trx)

Check whether the transaction has already been rolled back because it was selected as a deadlock victim, or if it has to wait then cancel the wait lock.

Returns
DB_DEADLOCK, DB_LOCK_WAIT or DB_SUCCESS
Parameters
trxin/out: trx lock state

◆ lock_trx_has_rec_x_lock()

bool lock_trx_has_rec_x_lock ( que_thr_t thr,
const dict_table_t table,
const buf_block_t block,
ulint  heap_no 
)

Check if the transaction holds an exclusive lock on a record.

Parameters
[in]thrquery thread of the transaction
[in]tabletable to check
[in]blockbuffer block of the record
[in]heap_norecord heap number
Returns
whether the locks are held

◆ lock_trx_holds_autoinc_locks()

static bool lock_trx_holds_autoinc_locks ( const trx_t trx)
static

Check if a transaction holds any autoinc locks.

Returns
true if the transaction holds any AUTOINC locks.
Parameters
trxin: transaction

◆ lock_trx_lock_list_init()

void lock_trx_lock_list_init ( trx_lock_list_t *  lock_list)

Initialise the trx lock list.

Parameters
lock_listList to initialise

◆ lock_trx_print_locks()

static bool lock_trx_print_locks ( FILE *  file,
const trx_t trx,
TrxLockIterator iter,
bool  load_block 
)
static

Prints info of locks for a transaction.

Returns
true if all printed, false if latches were released.
Parameters
filein/out: File to write
trxin: current transaction
iterin: transaction lock iterator
load_blockin: if true then read block from disk

◆ lock_trx_print_wait_and_mvcc_state()

void lock_trx_print_wait_and_mvcc_state ( FILE *  file,
const trx_t trx 
)

Prints transaction lock wait and MVCC state.

Parameters
[in,out]filefile where to print
[in]trxtransaction

◆ lock_trx_release_locks()

void lock_trx_release_locks ( trx_t trx)

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

Change the state of the transaction to TRX_STATE_COMMITTED_IN_MEMORY.

Doing an implicit to explicit conversion should not be expensive.

Parameters
trxin/out: transaction

◆ lock_trx_release_read_locks()

void lock_trx_release_read_locks ( trx_t trx,
bool  only_gap 
)

Release read locks of a transaction.

It is called during XA prepare to release locks early.

Parameters
[in,out]trxtransaction
[in]only_gaprelease only GAP locks

◆ lock_trx_release_read_locks_in_x_mode()

static void lock_trx_release_read_locks_in_x_mode ( trx_t trx,
bool  only_gap 
)
static

Release read locks of a transacion 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

◆ lock_trx_table_locks_find()

static bool lock_trx_table_locks_find ( const trx_t trx,
const lock_t find_lock 
)
static

Check if the lock exists in the trx_t::trx_lock_t::table_locks vector.

Parameters
[in]trxthe trx to validate
[in]find_locklock to find
Returns
true if found

◆ lock_trx_table_locks_remove()

static void lock_trx_table_locks_remove ( const lock_t lock_to_remove)
static

Removes lock_to_remove from lock_to_remove->trx->lock.table_locks.

Parameters
[in]lock_to_removelock to remove

◆ lock_unlock_table_autoinc()

void lock_unlock_table_autoinc ( trx_t trx)

Unlocks AUTO_INC type locks that were possibly reserved by a trx.

This function should be called at the the end of an SQL statement, by the connection thread that owns the transaction (trx->mysql_thd).

Parameters
trxin/out: transaction

◆ lock_update_copy_and_discard()

void lock_update_copy_and_discard ( const buf_block_t new_block,
const buf_block_t block 
)

Updates the lock table when a page is copied to another and the original page is removed from the chain of leaf pages, except if page is the root!

in: index page; NOT the root!

Parameters
new_blockin: index page to which copied
blockin: index page; NOT the root!

◆ lock_update_delete()

void lock_update_delete ( const buf_block_t block,
const rec_t rec 
)

Updates the lock table when a record is removed.

Parameters
blockin: buffer block containing rec
recin: the record to be removed

◆ lock_update_discard()

void lock_update_discard ( const buf_block_t heir_block,
ulint  heir_heap_no,
const buf_block_t block 
)

Updates the lock table when a page is discarded.

Parameters
heir_blockin: index page which will inherit the locks
heir_heap_noin: heap_no of the record which will inherit the locks
blockin: index page which will be discarded

◆ lock_update_insert()

void lock_update_insert ( const buf_block_t block,
const rec_t rec 
)

Updates the lock table when a new user record is inserted.

Parameters
blockin: buffer block containing rec
recin: the inserted record

◆ lock_update_merge_left()

void lock_update_merge_left ( const buf_block_t left_block,
const rec_t orig_pred,
const buf_block_t right_block 
)

Updates the lock table when a page is merged to the left.

Parameters
left_blockin: left page to which merged
orig_predin: original predecessor of supremum on the left page before merge
right_blockin: merged index page which will be discarded

◆ lock_update_merge_right()

void lock_update_merge_right ( const buf_block_t right_block,
const rec_t orig_succ,
const buf_block_t left_block 
)

Updates the lock table when a page is merged to the right.

Parameters
right_blockin: right page to which merged
orig_succin: original successor of infimum on the right page before merge
left_blockin: merged index page which will be discarded

◆ lock_update_root_raise()

void lock_update_root_raise ( const buf_block_t block,
const buf_block_t root 
)

Updates the lock table when the root page is copied to another in btr_root_raise_and_insert.

Note that we leave lock structs on the root page, even though they do not make sense on other than leaf pages: the reason is that in a pessimistic update the infimum record of the root page will act as a dummy carrier of the locks of the record to be updated.

Parameters
blockin: index page to which copied
rootin: root page

◆ lock_update_split_left()

void lock_update_split_left ( const buf_block_t right_block,
const buf_block_t left_block 
)

Updates the lock table when a page is split to the left.

Parameters
right_blockin: right page
left_blockin: left page

◆ lock_update_split_right()

void lock_update_split_right ( const buf_block_t right_block,
const buf_block_t left_block 
)

Updates the lock table when a page is split to the right.

Parameters
right_blockin: right page
left_blockin: left page

◆ lock_update_wait_for_edge()

static void lock_update_wait_for_edge ( const lock_t waiting_lock,
const lock_t blocking_lock 
)
static

Given a waiting_lock, and blocking_lock which is the reason it has to wait, makes sure that the (only) edge in the wait-for graph outgoing from the waiting_lock->trx points to blocking_lock->trx.

Parameters
[in]waiting_lockA lock waiting in queue, blocked by blocking_lock
[in]blocking_lockA lock which is a reason the waiting_lock has to wait

◆ lock_validate()

bool lock_validate ( )

Validates the lock system.

Returns
true if ok

◆ lock_validate_table_locks()

static bool lock_validate_table_locks ( const trx_ut_list_t *  trx_list)
static

Validates the table locks.

Returns
true if ok
Parameters
trx_listin: trx list

Variable Documentation

◆ innobase_deadlock_detect

bool innobase_deadlock_detect = true

◆ lock_cached_lock_mode_names

std::unordered_map<uint, const char *> lock_cached_lock_mode_names
static

Used by lock_get_mode_str to cache results.

Strings pointed by these pointers might be in use by performance schema and thus can not be freed until the very end. Protected by exclusive global lock_sys latch.

◆ lock_constant_names

const std::map<uint, const char *> lock_constant_names
static
Initial value:
{
{LOCK_GAP, "GAP"},
{LOCK_REC_NOT_GAP, "REC_NOT_GAP"},
{LOCK_INSERT_INTENTION, "INSERT_INTENTION"},
{LOCK_PREDICATE, "PREDICATE"},
{LOCK_PRDT_PAGE, "PRDT_PAGE"},
}
#define LOCK_PRDT_PAGE
Page lock.
Definition: lock0lock.h:940
#define LOCK_GAP
when this bit is set, it means that the \ lock holds only on the gap before the record; \ for instanc...
Definition: lock0lock.h:893
#define LOCK_REC_NOT_GAP
this bit means that the lock is only on \ the index record and does NOT block inserts \ to the gap be...
Definition: lock0lock.h:907
#define LOCK_INSERT_INTENTION
this bit is set when we place a waiting \ gap type record lock request in order to let \ an insert of...
Definition: lock0lock.h:923
#define LOCK_PREDICATE
Predicate lock.
Definition: lock0lock.h:939

Used by lock_get_mode_str to build a lock mode description.

◆ lock_deadlock_found

bool lock_deadlock_found = false
static

We store info on the latest deadlock error to this buffer.

InnoDB Monitor will then fetch it and print

◆ lock_latest_err_file

FILE* lock_latest_err_file
static

Only created if !srv_read_only_mode.

I/O operations on this file require exclusive lock_sys latch

◆ lock_sys

lock_sys_t* lock_sys = nullptr

The lock system.

◆ REC_LOCK_CACHE

const ulint REC_LOCK_CACHE = 8
static

Total number of cached record locks.

◆ REC_LOCK_SIZE

const ulint REC_LOCK_SIZE = sizeof(ib_lock_t) + 256
static

Maximum record lock size in bytes.

◆ TABLE_LOCK_CACHE

const ulint TABLE_LOCK_CACHE = 8
static

Total number of cached table locks.

◆ TABLE_LOCK_SIZE

const ulint TABLE_LOCK_SIZE = sizeof(ib_lock_t)
static

Size in bytes, of the table lock instance.