MySQL 9.1.0
Source Code Documentation
|
The transaction lock system. More...
#include <mysql/service_thd_engine_lock.h>
#include <sys/types.h>
#include <algorithm>
#include <bit>
#include <set>
#include <unordered_map>
#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 "os0thread.h"
#include "pars0pars.h"
#include "row0mysql.h"
#include "row0sel.h"
#include "srv0mon.h"
#include "trx0purge.h"
#include "trx0sys.h"
#include "usr0sess.h"
#include "ut0bitset.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 | locksys::Conflicting |
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 RW trx_sys lists only. More... | |
Namespaces | |
namespace | locksys |
Macros | |
#define | LOCK_MODULE_IMPLEMENTATION |
#define | PRINT_NUM_OF_LOCK_STRUCTS |
Typedefs | |
template<typename T > | |
using | Locks = std::vector< T, mem_heap_allocator< T > > |
Enumerations | |
enum class | locksys::Conflict { locksys::HAS_TO_WAIT , locksys::NO_CONFLICT , locksys::CAN_BYPASS } |
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 void | 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 next_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 uint64_t | lock_rec_lock_hash_value (const lock_t *lock) |
Calculates the hash 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... | |
bool | lock_is_waiting (const lock_t &lock) |
Checks if the lock is waiting (as opposed to granted). More... | |
static 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... | |
static ulint | lock_rec_get_gap (const lock_t *lock) |
Gets the gap flag of a record lock. More... | |
static ulint | lock_rec_get_rec_not_gap (const lock_t *lock) |
Gets the LOCK_REC_NOT_GAP flag of a record lock. More... | |
static ulint | lock_rec_get_insert_intention (const lock_t *lock) |
Gets the waiting insert flag of a record lock. More... | |
static Conflict | locksys::rec_lock_check_conflict (const trx_t *trx, ulint type_mode, const lock_t *lock2, bool lock_is_on_supremum, Trx_locks_cache &trx_locks_cache) |
Checks if a new request for a record lock has to wait for existing request. More... | |
static bool | locksys::rec_lock_has_to_wait (const lock_t *lock1, const lock_t *lock2, Trx_locks_cache &lock1_cache) |
Checks if a record lock request lock1 has to wait for request lock2. More... | |
bool | locksys::has_to_wait (const lock_t *lock1, const lock_t *lock2, Trx_locks_cache &lock1_cache) |
Checks if a lock request lock1 has to wait for request lock2. 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... | |
static byte | lock_rec_reset_nth_bit (lock_t *lock, ulint i) |
Reset the nth bit of a record lock. More... | |
bool | lock_rec_clear_request_no_wakeup (lock_t *lock, uint16_t heap_no) |
Reset the nth bit of a record lock. More... | |
static bool | lock_rec_has_any (Locks_hashtable &hash, page_id_t page_id) |
static bool | lock_rec_has_any (Locks_hashtable &hash, page_id_t page_id, uint16_t heap_no) |
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_t * | lock_rec_copy (const lock_t *lock, mem_heap_t *heap) |
Copies a record lock to heap. More... | |
static const lock_t * | lock_rec_has_expl (ulint precise_mode, const page_id_t page_id, uint32_t 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_t * | lock_rec_has_expl (ulint precise_mode, const buf_block_t *block, ulint heap_no, const trx_t *trx) |
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) |
Checks if some other transaction has a lock request in the queue. More... | |
static locksys::Conflicting | lock_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 bool | can_older_trx_be_still_active (trx_id_t max_old_active_id) |
Checks if the (-infinity,max_old_active_id] range contains an id of a currently active transaction which has modified a record. More... | |
static trx_t * | lock_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 (Locks_hashtable &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 (Locks_hashtable &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 bool | lock_edge_may_survive_prepare (const lock_t *waiting_lock, const lock_t *blocking_lock) |
Checks if the waits-for edge between waiting_lock and blocking_lock may survive PREPARE of the blocking_lock->trx. More... | |
static void | lock_report_wait_for_edge_to_server (const lock_t *waiting_lock, const lock_t *blocking_lock) |
static void | lock_create_wait_for_edge (const lock_t *waiting_lock, const lock_t *blocking_lock) |
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... | |
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... | |
static 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_t * | lock_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_t * | lock_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_t * | lock_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 const lock_t * | lock_find_record_lock_by_guid (Locks_hashtable &lock_hash, page_id_t page_id, const lock_guid_t &guid) |
const lock_t * | lock_find_record_lock_by_guid (page_id_t page_id, const lock_guid_t &guid) |
Inspect the lock queues associated with the given page_id in search for a lock which has guid equal to the given one. More... | |
static void | lock_rec_free_all_from_discard_page_low (page_id_t page_id, Locks_hashtable &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 (Locks_hashtable &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... | |
static 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, uint16_t heir_heap_no, uint16_t 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 (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 (trx_lock_list_t &lock_list) |
Move all the granted locks to the front of the given lock list. 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_point (const buf_block_t *right_block, const buf_block_t *left_block) |
Requests the Lock System to update record locks regarding the gap between the last record of the left_page and the first record of the right_page when the caller is about to prepended a new record as the first record on the right page, even though it should "naturally" be inserted as the last record of the left_page according to the information in the higher levels of the index. 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... | |
static 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. More... | |
static void | lock_table_pop_autoinc_locks (trx_t *trx) |
Pops autoinc lock requests from the transaction's autoinc_locks. More... | |
static void | lock_table_remove_autoinc_lock (lock_t *lock, trx_t *trx) |
Removes an autoinc lock request from the transaction's autoinc_locks. More... | |
const lock_t * | lock_find_table_lock_by_guid (const dict_table_t *table, const lock_guid_t &guid) |
Inspect the lock queue associated with the given table in search for a lock which has guid equal to the given one. More... | |
static 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, const lock_t *blocking_lock) |
Enqueues a waiting request for a table lock which cannot be granted immediately. More... | |
static 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. 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_t * | lock_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 bool | lock_release_read_lock (lock_t *lock, bool only_gap) |
Used to release a lock during PREPARE. 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 bool | locksys::try_release_read_locks_in_x_mode (trx_t *trx, bool only_gap) |
Release read locks of a transaction latching the whole lock-sys in exclusive mode, which is a bit too expensive to do by default. More... | |
void | lock_trx_release_read_locks (trx_t *trx, bool only_gap) |
Release read locks of a transaction. More... | |
static bool | locksys::try_release_all_locks (trx_t *trx) |
Releases transaction locks, and releases possible other transactions waiting because of these locks. More... | |
static bool | IS_LOCK_S_OR_X (lock_t *lock) |
static void | lock_remove_all_on_table_for_trx (dict_table_t *table, trx_t *trx, bool 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, bool 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 size_t | 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_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 void | lock_validate_table_locks () |
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, bool *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... | |
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... | |
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... | |
static 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... | |
trx_id_t | lock_get_trx_id (const lock_t *lock) |
Gets the id of the transaction owning a 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 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... | |
static dict_table_t * | lock_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_t & | lock_get_table_name (const lock_t *lock) |
Determine which table a lock is associated with. More... | |
const dict_index_t * | lock_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 (trx_t *trx) |
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... | |
bool | lock_cancel_if_waiting_and_release (const TrxVersion trx_version) |
Cancels the waiting lock request of the trx, if any. More... | |
static const lock_t * | lock_table_locks_lookup (const dict_table_t *table) |
Scans all locks of all transactions in the rw_trx_list searching for any lock (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_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... | |
static std::mutex | lock_cached_lock_mode_names_mutex |
Mutex protecting access to lock_cached_lock_mode_names. More... | |
lock_sys_t * | lock_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... | |
constexpr auto | locksys::MAX_CS_DURATION = std::chrono::seconds{1} |
We don't want to hold the Global latch for too long, even in S mode, not to starve threads waiting for X-latch on it such as lock_wait_timeout_thread(). More... | |
The transaction lock system.
Created 5/7/1996 Heikki Tuuri
#define LOCK_MODULE_IMPLEMENTATION |
#define PRINT_NUM_OF_LOCK_STRUCTS |
using Locks = std::vector<T, mem_heap_allocator<T> > |
|
static |
Checks if the (-infinity,max_old_active_id] range contains an id of a currently active transaction which has modified a record.
The premise is that the caller has seen a record modified by a trx with trx->id <= max_old_active_id, and wants to know if it might be still active. It may err on the safe side.
[in] | max_old_active_id | The end of the range inclusive. For example found in the PAGE_MAX_TRX_ID field of a header of a secondary index page. |
false | the caller may assume that if before the call it saw a record modified by trx_id, and trx_id < max_old_active_id, then it is no longer active |
true | the caller should double check in a synchronized way if the seen trx_id is still active or not |
|
inlinestatic |
bool lock_cancel_if_waiting_and_release | ( | TrxVersion | trx_version | ) |
Cancels the waiting lock request of the trx, if any.
If the transaction has already committed (trx->version has changed) or is no longer waiting for a lock (trx->lock.blocking_trx is nullptr) this function will not cancel the waiting lock.
[in] | trx_version | The trx we want to wake up and its expected version |
void lock_cancel_waiting_and_release | ( | trx_t * | trx | ) |
Cancels a waiting lock request and releases possible other transactions waiting behind it.
[in,out] | trx | The transaction waiting for a lock |
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.
Emits an error otherwise.
[in] | trx_id | The trx id to check, found in user record or secondary index page header |
[in] | rec | The user record which contained the trx_id in its header or in header of its page |
[in] | index | The index which contained the rec |
[in] | offsets | The result of rec_get_offsets(rec, index) |
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.
rec | in: user record which should be read or passed over by a read cursor |
index | in: clustered index |
offsets | in: rec_get_offsets(rec, index) |
view | in: consistent read view |
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.
flags | in: if BTR_NO_LOCKING_FLAG bit is set, does nothing |
block | in: buffer block of rec |
rec | in: record which should be modified |
index | in: clustered index |
offsets | in: rec_get_offsets(rec, index) |
thr | in: query thread |
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.
[in] | duration | If 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] | block | buffer block of rec |
[in] | rec | user record or page supremum record which should be read or passed over by a read cursor |
[in] | index | secondary index |
[in] | offsets | rec_get_offsets(rec, index) |
[in] | sel_mode | select mode: SELECT_ORDINARY, SELECT_SKIP_LOKCED, or SELECT_NO_WAIT |
[in] | mode | 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 |
[in] | gap_mode | LOCK_ORDINARY, LOCK_GAP, or LOCK_REC_NOT_GAP |
[in,out] | thr | query thread |
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".
block | in: buffer block of rec |
rec | in: user record or page supremum record which should be read or passed over by a read cursor |
index | in: clustered index |
mode | in: 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_mode | in: LOCK_ORDINARY, LOCK_GAP, or LOCK_REC_NOT_GAP |
thr | in: query thread |
|
static |
Creates a new edge in wait-for graph, from waiter to blocker.
[in] | waiting_lock | A lock waiting in queue, blocked by blocking_lock |
[in] | blocking_lock | A lock which is a reason the waiting_lock has to wait |
|
static |
Checks if the waits-for edge between waiting_lock and blocking_lock may survive PREPARE of the blocking_lock->trx.
For transactions in low isolation levels we release some of the locks during PREPARE.
[in] | waiting_lock | A lock waiting in queue, blocked by blocking_lock |
[in] | blocking_lock | A lock which is a reason the waiting_lock has to wait |
true | the waiting_lock->trx MAY have to wait for blocking_lock->trx even if blocking_lock->trx PREPAREs. |
false | the waiting_lock->trx CERTAINLY will not have to wait for blocking_lock->trx for this particular reason. |
|
static |
const lock_t * lock_find_record_lock_by_guid | ( | page_id_t | page_id, |
const lock_guid_t & | guid | ||
) |
Inspect the lock queues associated with the given page_id in search for a lock which has guid equal to the given one.
Caller should hold a latch on shard containing locks for this page.
[in] | page_id | the id of the page, for which we expect the lock |
[in] | guid | the guid of the lock we seek for |
const lock_t * lock_find_table_lock_by_guid | ( | const dict_table_t * | table, |
const lock_guid_t & | guid | ||
) |
Inspect the lock queue associated with the given table in search for a lock which has guid equal to the given one.
Caller should hold a latch on the shard containing this table's locks.
[in] | table | the table, for which we expect the lock |
[in] | guid | the guid of the lock we seek for |
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:
lock | in: lock |
|
static |
Calculates the number of record lock structs in the record lock hash table.
Get the performance schema event (thread_id, event_id) that created the lock.
[in] | lock | Lock |
[out] | thread_id | Thread ID that created the lock |
[out] | event_id | Event ID that created the lock |
ulint lock_get_size | ( | void | ) |
Gets the size of a lock struct.
|
inlinestatic |
Gets the table on which the lock is.
lock | in: lock |
table_id_t lock_get_table_id | ( | const lock_t * | lock | ) |
Gets the id of the table on which the lock is.
lock | in: lock |
const table_name_t & lock_get_table_name | ( | const lock_t * | lock | ) |
Determine which table a lock is associated with.
[in] | lock | the lock |
Gets the id of the transaction owning a lock.
[in] | lock | A lock of the transaction we are interested in |
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.
lock | in: lock |
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.
lock | in: 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.
[in,out] | lock | waiting lock request |
|
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.
[in] | lock | A lock in WAITING state, which perhaps can be granted now |
|
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.
Checks if a lock request lock1 has to wait for request lock2.
[in] | lock1 | A waiting lock |
[in] | lock2 | 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 lock |
|
static |
Checks if a waiting lock request still has to wait in a queue.
[in] | wait_lock | Waiting lock |
[in] | blocking_trx | If 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. |
bool lock_is_waiting | ( | const lock_t & | lock | ) |
Checks if the lock is waiting (as opposed to granted).
Caller should hold a latch on shard containging the lock in order for this check to be meaningful.
[in] | lock | the lock to inspect |
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.
[in] | trx | High Priority transaction |
[in,out] | hit_list | List of transactions which need to be rolled back |
|
static |
Collect the transactions that will need to be rolled back asynchronously.
[in,out] | hit_list | The list of transactions to be rolled back, to which the trx should be appended. |
[in] | hp_trx_id | The id of the blocked High Priority Transaction |
[in,out] | trx | The blocking transaction to be rolled back |
|
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.
[in,out] | lock_list | the given lock list. |
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.
[in] | new_block | Index page to move to |
[in] | block | Index page |
[in,out] | rec | Record on page: this is the first record moved |
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.
[in] | new_block | Index page to move to |
[in] | block | Index page |
[in,out] | rec | Record on page: this is the first record not copied |
[in] | old_end | Old previous-to-last record on new_page before the records were copied |
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.
block | in: old index page, now reorganized |
oblock | in: copy of the old, not reorganized page |
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)
[in] | trxs_on_cycle | trxs causing deadlock, i-th waits for i+1-th |
[in] | victim_trx | the trx from trx_on_cycle which will be rolled back |
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.
[in] | trx_lock | transaction locks |
Return the number of table locks for a transaction.
The caller must be holding trx->mutex.
[in] | trx | the transaction for which we want the number of table locks |
void lock_on_statement_end | ( | trx_t * | trx | ) |
Called to inform lock-sys that a statement processing for a trx has just finished.
[in] | trx | transaction which has finished processing a statement |
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).
[in,out] | file | the file where to print |
void lock_print_info_summary | ( | FILE * | file | ) |
Prints info of locks for all transactions.
[in] | file | file where to print |
|
inlinestatic |
|
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!
[in] | type_mode | lock mode, wait, gap etc. flags; type is ignored and replaced by LOCK_REC |
[in] | block | buffer block containing the record |
[in] | heap_no | heap number of the record |
[in] | index | index of record |
[in,out] | trx | transaction |
[in] | we_own_trx_mutex | true iff the caller own trx->mutex (optional). Defaults to false. |
|
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.
lock | in: record lock |
|
static |
Validate a record lock's block.
|
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!
lock | in: waiting record lock request |
bool lock_rec_clear_request_no_wakeup | ( | lock_t * | lock, |
uint16_t | heap_no | ||
) |
Reset the nth bit of a record lock.
If this was a wait lock clears the wait flag on it, and marks that the trx no longer waits on it, but doesn't wake up the transaction. This function is meant to be used when lock requests are moved from one place to another, and thus a new (equivalent) lock request will be soon created for the transaction, so there's no point in waking it up.
[in,out] | lock | record lock |
[in] | heap_no | index of the bit that will be reset |
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.
[in] | block | buffer block of rec |
[in] | rec | user record on page |
[in] | index | index of record |
[in] | offsets | rec_get_offsets(rec, index) |
|
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.
block | in: buffer block of rec |
rec | in: user record on page |
index | in: index of record |
offsets | in: rec_get_offsets(rec, index) |
trx | in/out: active transaction |
heap_no | in: rec heap number to lock |
|
static |
Copies a record lock to heap.
lock | in: record lock |
heap | in: memory heap |
|
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.
[in,out] | in_lock | record 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 |
void lock_rec_discard | ( | lock_t * | in_lock | ) |
Removes a record lock request, waiting or granted, from the queue.
[in] | in_lock | record lock object: all record locks which are contained in this lock object are removed |
bool lock_rec_expl_exist_on_page | ( | const page_id_t & | page_id | ) |
Determines if there are explicit record locks on a page.
[in] | page_id | space id and page number |
|
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.
[in] | lock | the record lock |
Looks for the next set bit in the record lock bitmap.
[in] | lock | record lock with at least one bit set |
[in] | heap_no | current set bit |
Looks for a set bit in a record lock bitmap.
Returns ULINT_UNDEFINED, if none found.
[in] | lock | A record lock |
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.
block | in: page to be discarded |
|
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.
Gets the gap flag of a record lock.
lock | in: record lock |
const dict_index_t * lock_rec_get_index | ( | const lock_t * | lock | ) |
For a record lock, gets the index on which the lock is.
lock | in: lock |
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.
lock | in: lock |
Gets the waiting insert flag of a record lock.
lock | in: record lock |
For a record lock, gets the tablespace number and page number on which the lock is.
Gets the LOCK_REC_NOT_GAP flag of a record lock.
lock | in: record 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 cell (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.
[in,out] | in_lock | record lock object: grant all non-conflicting locks waiting behind this lock object |
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.
[in] | in_lock | Lock which was released, or partially released by modifying its type/mode (see lock_trx_release_read_locks) or resetting heap_no-th bit in the bitmap (see lock_rec_release) |
[in] | heap_no | Heap number within the page on which the lock was (or still is) held |
|
static |
|
static |
|
inlinestatic |
|
inlinestatic |
Checks if a transaction has a GRANTED explicit lock on rec stronger or equal to precise_mode.
[in] | precise_mode | LOCK_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] | page_id | id of the page containing the record |
[in] | heap_no | heap number of the record |
[in] | trx | transaction |
|
static |
Checks if a waiting record lock request still has to wait for granted locks.
[in] | wait_lock | Waiting record lock |
[in] | granted | Granted record locks |
[in] | new_granted_index | Start of new granted locks |
|
static |
Checks if a waiting record lock request still has to wait in a queue.
[in] | wait_lock | Waiting record lock |
[in] | blocking_trx | If 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) |
|
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.
heir_block | in: block containing the record which inherits |
block | in: block containing the record from which inherited; does NOT reset the locks on this record |
heir_heap_no | in: heap_no of the inheriting record |
heap_no | in: heap_no of the donating record |
|
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.
block | in: buffer block |
heir_heap_no | in: heap_no of record which inherits |
heap_no | in: heap_no of record from which inherited; does NOT reset the locks on this record |
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, | ||
bool * | 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.
flags | in: if BTR_NO_LOCKING_FLAG bit is set, does nothing |
rec | in: record after which to insert |
block | in/out: buffer block of rec |
index | in: index |
thr | in: query thread |
mtr | in/out: mini-transaction |
inherit | out: set to true if the new inserted record maybe should inherit LOCK_GAP type locks from the successor record |
|
static |
Insert lock record to the head of the queue where the GRANTED locks reside.
[in,out] | lock_hash | Hash table containing the locks |
[in,out] | lock | Record lock instance to insert |
[in] | rec_id | Record being locked |
|
static |
Insert lock record to the tail of the queue where the WAITING locks reside.
[in,out] | lock_hash | Hash table containing the locks |
[in,out] | lock | Record lock instance to insert |
[in] | rec_id | Record being locked |
|
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.
[in] | impl | if true, no lock is set if no wait is necessary: we assume that the caller will set an implicit lock |
[in] | sel_mode | select mode: SELECT_ORDINARY, SELECT_SKIP_LOCKED, or SELECT_NO_WAIT |
[in] | mode | lock mode: LOCK_X or LOCK_S possibly ORed to either LOCK_GAP or LOCK_REC_NOT_GAP |
[in] | block | buffer block containing the record |
[in] | heap_no | heap number of record |
[in] | index | index of record |
[in,out] | thr | query thread |
|
inlinestatic |
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.
impl | in: if true, no lock is set if no wait is necessary: we assume that the caller will set an implicit lock |
mode | in: lock mode: LOCK_X or LOCK_S possibly ORed to either LOCK_GAP or LOCK_REC_NOT_GAP |
block | in: buffer block containing the record |
heap_no | in: heap number of record |
index | in: index of record |
thr | in: query thread |
|
static |
Calculates the hash value of a lock: used in migrating the hash table.
[in] | lock | record lock object |
|
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.
[in] | impl | if true, no lock might be set if no wait is necessary: we assume that the caller will set an implicit lock |
[in] | sel_mode | select mode: SELECT_ORDINARY, SELECT_SKIP_LOCKED, or SELECT_NO_WAIT |
[in] | mode | lock mode: LOCK_X or LOCK_S possibly ORed to either LOCK_GAP or LOCK_REC_NOT_GAP |
[in] | block | buffer block containing the record |
[in] | heap_no | heap number of record |
[in] | index | index of record |
[in,out] | thr | query thread |
|
static |
Moves the locks of a record to another record and resets the lock bits of the donating record.
receiver | in: buffer block containing the receiving record |
donator | in: buffer block containing the donating record |
receiver_heap_no | in: heap_no of the record which gets the locks; there must be no lock requests on it! |
donator_heap_no | in: heap_no of the record which gives the locks |
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 hash cell.
[in] | lock | a granted lock to be moved |
[in] | rec_id | record id which specifies particular queue and hash cell |
|
static |
Checks if some other transaction has a conflicting explicit lock request in the queue, so that we have to wait.
[in] | mode | LOCK_S or LOCK_X, possibly ORed to LOCK_GAP or LOC_REC_NOT_GAP, LOCK_INSERT_INTENTION |
[in] | block | buffer block containing the record |
[in] | heap_no | heap number of the record |
[in] | trx | our transaction |
|
static |
Checks if some other transaction has a lock request in the queue.
mode | in: LOCK_S or LOCK_X |
block | in: buffer block containing the record |
wait | in: whether also waiting locks are taken into account |
heap_no | in: heap number of the record |
trx | in: transaction, or NULL if requests by all transactions are taken into account |
|
static |
Checks if some transaction, other than given trx_id, has an explicit lock on the given rec, in the given precise_mode.
[in] | precise_mode | LOCK_S or LOCK_X possibly ORed to LOCK_GAP or LOCK_REC_NOT_GAP. |
[in] | trx | the trx holding implicit lock on rec |
[in] | rec | user record |
[in] | block | buffer block containing the record |
|
static |
Prints info of a record lock.
file | in: file where to print |
lock | in: record type lock |
Grant a lock to waiting transactions.
[in] | lock | Lock that was unlocked |
[in] | heap_no | Heap no within the page for the lock. |
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.
[in] | heir_block | Block containing the record which inherits |
[in] | block | Block containing the record from which inherited; does not reset the locks on this record |
[in] | heir_heap_no | Heap_no of the inheriting record |
[in] | heap_no | Heap_no of the donating record |
|
static |
Resets the lock bits for a single record.
Releases transactions waiting for lock requests here.
block | in: buffer block containing the record |
heap_no | in: heap number of record |
|
static |
Resets the lock bits for a single record.
Releases transactions waiting for lock requests here.
hash | in: hash table |
block | in: buffer block containing the record |
heap_no | in: heap number of record |
Reset the nth bit of a record lock.
[in,out] | lock | record lock |
[in] | i | index of the bit that will be reset |
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.
[in] | block | Buffer block containing rec |
[in] | rec | Record whose lock state is restored |
[in] | donator | Page (rec is not necessarily on this page) whose infimum stored the lock state; lock bits are reset on the 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.
block | in: buffer block containing rec |
rec | in: record whose lock state is stored on the infimum record of the same page; lock bits are reset on the record |
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_try_unlock, and it assumes that the lock we are looking for has LOCK_REC_NOT_GAP flag.
trx | in/out: transaction that has set a record lock |
block | in: buffer block containing rec |
rec | in: record |
lock_mode | in: LOCK_S or LOCK_X |
|
static |
Validates the record lock queues on a page.
[in] | block | A (possibly freed) block for which we want to validate all lock queues. If any of the queues is non-empty we additionally assert that the block was not freed. |
block | in: buffer block |
|
inlinestatic |
Release the last lock from the transaction's autoinc locks.
[in] | trx | trx which vector of AUTOINC locks to modify |
|
static |
Release all the transaction's autoinc locks.
trx | in/out: transaction |
|
static |
Unlock the GAP Lock part of a Next Key Lock and grant it to waiters (if any)
[in,out] | lock | lock object |
|
static |
Used to release a lock during PREPARE.
The lock is only released if rules permit it.
[in] | lock | the lock that we consider releasing |
[in] | only_gap | true if we don't want to release records, just the gaps between them |
void lock_remove_all_on_table | ( | dict_table_t * | table, |
bool | 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.
table | in: table to be dropped or discarded |
remove_also_table_sx_locks | in: also removes table S and X 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.
table | in: table to be dropped |
trx | in: a transaction |
remove_also_table_sx_locks | in: also removes table S and X locks |
|
static |
Remove any explicit record locks held by recovering transactions on the table.
table | in: check if there are any locks held on records in this table or on the table itself |
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 | next_trx_id | ||
) |
Reports that a transaction id is insensible, i.e., in the future.
[in] | trx_id | Trx id |
[in] | rec | User record |
[in] | index | Index |
[in] | offsets | Rec_get_offsets(rec, index) |
[in] | next_trx_id | value received from trx_sys_get_next_trx_id_or_no() |
|
static |
|
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.
[in] | held_lock | a lock granted to trx which is at least as strong as mode|LOCK_REC_NOT_GAP |
[in] | mode | requested lock mode: LOCK_X or LOCK_S |
[in] | block | buffer block containing the record to be locked |
[in] | heap_no | heap number of the record to be locked |
[in] | index | index of record to be locked |
[in] | trx | the transaction requesting the Next Key Lock |
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.
[in] | new_block | Index page to move to |
[in] | block | Index page |
[in] | rec_move | Recording records moved |
[in] | num_move | Num of rec to move |
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.
rec | in: user record which should be read or passed over by a read cursor |
index | in: index |
view | in: consistent read view |
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.
flags | in: if BTR_NO_LOCKING_FLAG bit is set, does nothing |
block | in/out: buffer block of rec |
rec | in: 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 |
index | in: secondary index |
thr | in: query thread (can be NULL if BTR_NO_LOCKING_FLAG) |
mtr | in/out: mini-transaction |
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.
[in] | duration | If 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] | block | buffer block of rec |
[in] | rec | user record or page supremum record which should be read or passed over by a read cursor |
[in] | index | secondary index |
[in] | offsets | rec_get_offsets(rec, index) |
[in] | sel_mode | select mode: SELECT_ORDINARY, SELECT_SKIP_LOKCED, or SELECT_NO_WAIT |
[in] | mode | 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 |
[in] | gap_mode | LOCK_ORDINARY, LOCK_GAP, or LOCK_REC_NOT_GAP |
[in,out] | thr | query thread |
|
static |
Checks if some transaction has an implicit x-lock on a record in a secondary index.
[in] | rec | user record |
[in] | index | secondary index |
[in] | offsets | rec_get_offsets(rec, index) |
|
inlinestatic |
Sets the wait flag of a lock and the back pointer in trx to lock.
[in] | lock | The lock on which a transaction is waiting |
void lock_set_timeout_event | ( | ) |
Set the lock system timeout event.
void lock_sys_close | ( | void | ) |
Closes the lock system at database shutdown.
void lock_sys_create | ( | ulint | n_cells | ) |
Creates the lock system at database start.
in: number of slots in lock hash table
n_cells | in: number of slots in lock hash table |
void lock_sys_resize | ( | ulint | n_cells | ) |
Resize the lock hash tables.
[in] | n_cells | number of slots in lock hash 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.
flags | in: if BTR_NO_LOCKING_FLAG bit is set, does nothing |
table | in/out: database table in dictionary cache |
mode | in: lock mode |
thr | in: query thread |
|
inlinestatic |
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.
table | in/out: database table in dictionary cache |
type_mode | in: lock mode possibly ORed with LOCK_WAIT |
trx | in: trx |
|
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.
in_lock | in/out: table lock object; transactions waiting behind will get their lock requests granted, if they are now qualified to it |
|
static |
Enqueues a waiting request for a table lock which cannot be granted immediately.
Checks for deadlocks.
[in] | mode | lock mode this transaction is requesting |
[in] | table | the table to be locked |
[in] | thr | the query thread requesting the lock |
[in] | blocking_lock | the lock which is the reason this request has to wait |
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.
[in] | table | table to lock |
[in,out] | trx | transaction |
[in] | mode | LOCK_X or LOCK_S |
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.
[in] | table | the table |
The n_rec_locks field might be modified by operation on any page shard. This function is called in contexts where we believe that the number of locks should either be zero or decreasing. For such scenario of usage, we can read the n_rec_locks without any latch and restrict latch just to the table's shard and release it before return, which means true
could be a false-positive, but false
is certain.
|
static |
Checks if a waiting table lock request still has to wait in a queue.
[in] | wait_lock | Waiting table lock |
[in] | blocking_trx | If 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) |
void lock_table_ix_resurrect | ( | dict_table_t * | table, |
trx_t * | trx | ||
) |
Creates a table IX lock object for a resurrected transaction.
[in,out] | table | Table |
[in,out] | trx | Transaction |
|
static |
Scans all locks of all transactions in the rw_trx_list searching for any lock (table or rec) against the table.
[in] | table | the table for which we perform the search |
|
inlinestatic |
Checks if other transactions have an incompatible mode lock request in the lock queue.
trx | in: transaction, or NULL if all transactions should be included |
wait | in: LOCK_WAIT if also waiting locks are taken into account, or 0 if not |
table | in: table |
mode | in: lock mode |
|
inlinestatic |
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.
trx | in/out: transaction that owns the AUTOINC locks |
|
static |
Prints info of a table lock.
file | in: file where to print |
lock | in: table type lock |
|
static |
Validates the lock queue on a table.
table | in: table |
Removes an autoinc lock request from the transaction's autoinc_locks.
lock | in: table lock |
trx | in/out: transaction that owns the lock |
|
inlinestatic |
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.
lock | in/out: table lock |
void lock_trx_alloc_locks | ( | trx_t * | trx | ) |
Allocate cached locks for the transaction.
trx | allocate cached record locks for this transaction |
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.
[in] | thr | query thread of the transaction |
[in] | table | table to check |
[in] | block | buffer block of the record |
[in] | heap_no | record heap number |
|
static |
Check if a transaction holds any autoinc locks.
trx | in: transaction |
|
static |
Prints info of locks for a transaction.
file | in/out: File to write |
trx | in: current transaction |
iter | in: transaction lock iterator |
load_block | in: if true then read block from disk |
void lock_trx_print_wait_and_mvcc_state | ( | FILE * | file, |
const trx_t * | trx | ||
) |
Prints transaction lock wait and MVCC state.
[in,out] | file | file where to print |
[in] | trx | transaction |
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.
trx | in/out: transaction |
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.
[in,out] | trx | transaction |
[in] | only_gap | release only GAP locks |
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).
trx | in/out: transaction |
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] | new_block | Index page to which copied |
[in] | block | Index page; not the root! |
void lock_update_delete | ( | const buf_block_t * | block, |
const rec_t * | rec | ||
) |
Updates the lock table when a record is removed.
[in] | block | Buffer block containing rec |
[in] | rec | The record to be removed |
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.
[in] | heir_block | Index page which will inherit the locks |
[in] | heir_heap_no | Heap_no of the record which will inherit the locks |
[in] | block | Index page which will be discarded |
void lock_update_insert | ( | const buf_block_t * | block, |
const rec_t * | rec | ||
) |
Updates the lock table when a new user record is inserted.
[in] | block | Buffer block containing rec |
[in] | rec | The inserted record |
block | in: buffer block containing rec |
rec | in: the inserted record |
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.
[in] | left_block | Left page to which merged |
[in] | orig_pred | Original predecessor of supremum on the left page before merge |
[in] | right_block | Merged index page which will be discarded |
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.
[in] | right_block | Right page to which merged |
[in] | orig_succ | Original successor of infimum on the right page before merge |
[in] | left_block | Merged index page which will be discarded |
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.
block | in: index page to which copied |
root | in: root page |
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.
[in] | right_block | Right page |
[in] | left_block | Left page |
void lock_update_split_point | ( | const buf_block_t * | right_block, |
const buf_block_t * | left_block | ||
) |
Requests the Lock System to update record locks regarding the gap between the last record of the left_page and the first record of the right_page when the caller is about to prepended a new record as the first record on the right page, even though it should "naturally" be inserted as the last record of the left_page according to the information in the higher levels of the index.
That is, we assume that the lowest common ancestor of the left_page and the right_page routes the key of the new record to the left_page, but a heuristic which tries to avoid overflowing the left_page has chosen to prepend the new record to the right_page instead. Said ancestor performs this routing by comparing the key of the record to a "split point" - the key associated with the right_page's subtree, such that all records larger than that split point are to be found in the right_page (or some even further page). Ideally this should be the minimum key in this whole subtree, however due to the way we optimize the DELETE and INSERT operations, we often do not update this information, so that such "split point" can actually be smaller than the real minimum. Still, even if not up-to-date, its value is always correct, in that it really separates the subtrees (keys smaller than "split point" are not in left_page and larger are not in right_page).
The reason this is important to Lock System, is that the gap between the last record on the left_page and the first record on the right_page is represented as two gaps:
Thus, inserting the new record, and subsequently adjusting "split points" in its ancestors to values smaller or equal to the new records' key, will mean that gap will be sliced at a different place ("moved to the left"): fragment of the 1st gap will now become treated as 2nd. Therefore, Lock System must copy any GRANTED locks from 1st gap to the 2nd gap. Any WAITING locks must be of INSERT_INTENTION type (as no other GAP locks ever wait for anything) and can stay at 1st gap, as their only purpose is to notify the requester they can retry insertion, and there's no correctness requirement to avoid waking them up too soon.
[in] | right_block | Right page |
[in] | left_block | Left page |
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.
[in] | right_block | Right page |
[in] | left_block | Left page |
|
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.
[in] | waiting_lock | A lock waiting in queue, blocked by blocking_lock |
[in] | blocking_lock | A lock which is a reason the waiting_lock has to wait |
bool lock_validate | ( | ) |
Validates the lock system.
|
static |
Validates the table locks.
bool innobase_deadlock_detect = true |
|
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_cached_lock_mode_names_mutex.
|
static |
Mutex protecting access to lock_cached_lock_mode_names.
|
static |
Used by lock_get_mode_str to build a lock mode description.
|
static |
We store info on the latest deadlock error to this buffer.
InnoDB Monitor will then fetch it and print
|
static |
Only created if !srv_read_only_mode.
I/O operations on this file require exclusive lock_sys latch
lock_sys_t* lock_sys = nullptr |
The lock system.
|
static |
Total number of cached record locks.
|
static |
Maximum record lock size in bytes.
|
static |
Total number of cached table locks.
|
static |
Size in bytes, of the table lock instance.