MySQL 9.1.0
Source Code Documentation
|
The transaction lock system. More...
#include "buf0types.h"
#include "dict0types.h"
#include "hash0hash.h"
#include "lock0types.h"
#include "mtr0types.h"
#include "que0types.h"
#include "rem0types.h"
#include "srv0srv.h"
#include "trx0types.h"
#include "univ.i"
#include "ut0vec.h"
#include "gis0rtree.h"
#include "lock0latches.h"
#include "lock0prdt.h"
#include "ut0sharded_bitset.h"
#include "lock0lock.ic"
#include "lock0guards.h"
Go to the source code of this file.
Classes | |
class | locksys::Trx_locks_cache |
An object which can be passed to consecutive calls to rec_lock_has_to_wait(trx, mode, lock, is_supremum, trx_locks_cache) for the same trx and heap_no (which is implicitly the bit common to all lock objects passed) which can be used by this function to cache some partial results. More... | |
struct | lock_op_t |
Lock operation struct. More... | |
struct | Locks_hashtable |
A hashmap used by lock sys, to organize locks by page (block), so that it is easy to maintain a list of all locks related to a given page by append(lock,..), prepend(lock,..), erase(lock,..), move_to_front(lock,...) while also providing ability to iterate over all locks related for a given page in that order. More... | |
struct | lock_sys_t |
The lock system struct. More... | |
Namespaces | |
namespace | locksys |
Typedefs | |
typedef ib_mutex_t | Lock_mutex |
Enumerations | |
enum class | lock_duration_t { REGULAR = 0 , AT_LEAST_STATEMENT = 1 } |
Used to specify the intended duration of a record lock. More... | |
Functions | |
ulint | lock_get_size (void) |
Gets the size of a lock struct. More... | |
void | lock_sys_create (ulint n_cells) |
Creates the lock system at database start. 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... | |
static ulint | lock_get_min_heap_no (const buf_block_t *block) |
Gets the heap_no of the smallest user record on a page. 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_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... | |
bool | lock_rec_expl_exist_on_page (const page_id_t &page_id) |
Determines if there are explicit record locks on a page. 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... | |
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... | |
void | lock_on_statement_end (trx_t *trx) |
Called to inform lock-sys that a statement processing for a trx has just finished. More... | |
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. More... | |
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. 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... | |
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... | |
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... | |
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... | |
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... | |
void | lock_trx_release_locks (trx_t *trx) |
Releases a transaction's locks, and releases possible other transactions waiting because of these locks. More... | |
void | lock_trx_release_read_locks (trx_t *trx, bool only_gap) |
Release read locks of a transaction. More... | |
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. 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 uint64_t | lock_rec_hash_value (const page_id_t &page_id) |
Calculates the hash value of a page file address: used in inserting or searching for a lock in the hash table or getting global shard index. 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... | |
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... | |
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... | |
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... | |
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... | |
void | lock_print_info_all_transactions (FILE *file) |
Prints info of locks for each transaction. 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... | |
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... | |
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... | |
bool | lock_table_has_locks (const dict_table_t *table) |
Check if there are any locks (table or rec) against table. More... | |
void | lock_wait_timeout_thread () |
A thread which wakes up threads whose lock wait may have lasted too long. More... | |
void | lock_wait_request_check_for_cycles () |
Notifies the thread which analyzes wait-for-graph that there was at least one new edge added or modified ( trx->blocking_trx has changed ), so that the thread will know it has to analyze it. More... | |
void | lock_wait_suspend_thread (que_thr_t *thr) |
Puts a user OS thread to wait for a lock to be released. More... | |
void | lock_unlock_table_autoinc (trx_t *trx) |
Unlocks AUTO_INC type locks that were possibly reserved by a trx. More... | |
bool | lock_cancel_if_waiting_and_release (TrxVersion trx_version) |
Cancels the waiting lock request of the trx, if any. More... | |
void | lock_set_timeout_event () |
Set the lock system timeout event. 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_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... | |
bool | lock_validate () |
Validates the lock system. More... | |
void | lock_trx_alloc_locks (trx_t *trx) |
Allocate cached locks for the transaction. 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... | |
void | lock_rec_discard (lock_t *in_lock) |
Removes a record lock request, waiting or granted, from the queue. 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_rec_free_all_from_discard_page (const buf_block_t *block) |
Removes record lock objects set on an index page which is discarded. More... | |
bool | lock_rec_clear_request_no_wakeup (lock_t *lock, uint16_t heap_no) |
Reset the nth bit of a record lock. More... | |
bool | lock_is_waiting (const lock_t &lock) |
Checks if the lock is waiting (as opposed to granted). 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... | |
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 bool | lock_wait_mutex_own () |
Test if lock_sys->wait_mutex is owned. More... | |
static void | lock_wait_mutex_enter () |
Acquire the lock_sys->wait_mutex. More... | |
static void | lock_wait_mutex_exit () |
Release the lock_sys->wait_mutex. More... | |
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... | |
Variables | |
bool | innobase_deadlock_detect |
lock_sys_t * | lock_sys |
The lock system. More... | |
constexpr uint32_t | LOCK_MODE_MASK = 0xF |
Lock modes and types. More... | |
constexpr uint32_t | LOCK_TABLE = 16 |
Lock types. More... | |
constexpr uint32_t | LOCK_REC = 32 |
record lock More... | |
constexpr uint32_t | LOCK_TYPE_MASK = 0xF0UL |
mask used to extract lock type from the type_mode field in a lock More... | |
constexpr uint32_t | LOCK_WAIT = 256 |
Waiting lock flag; when set, it means that the lock has not yet been granted, it is just waiting for its turn in the wait queue. More... | |
constexpr uint32_t | LOCK_ORDINARY = 0 |
this flag denotes an ordinary next-key lock in contrast to LOCK_GAP or LOCK_REC_NOT_GAP More... | |
constexpr uint32_t | LOCK_GAP = 512 |
when this bit is set, it means that the lock holds only on the gap before the record; for instance, an x-lock on the gap does not give permission to modify the record on which the bit is set; locks of this type are created when records are removed from the index chain of records More... | |
constexpr uint32_t | LOCK_REC_NOT_GAP = 1024 |
this bit means that the lock is only on the index record and does NOT block inserts to the gap before the index record; this is used in the case when we retrieve a record with a unique key, and is also used in locking plain SELECTs (not part of UPDATE or DELETE) when the user has set the READ COMMITTED isolation level More... | |
constexpr uint32_t | LOCK_INSERT_INTENTION = 2048 |
this bit is set when we place a waiting gap type record lock request in order to let an insert of an index record to wait until there are no conflicting locks by other transactions on the gap; note that this flag remains set when the waiting lock is granted, or if the lock is inherited to a neighboring record More... | |
constexpr uint32_t | LOCK_PREDICATE = 8192 |
Predicate lock. More... | |
constexpr uint32_t | LOCK_PRDT_PAGE = 16384 |
Page lock. More... | |
The transaction lock system.
Created 5/7/1996 Heikki Tuuri
typedef ib_mutex_t Lock_mutex |
|
strong |
Used to specify the intended duration of a record lock.
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 |
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.
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".
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 |
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 |
|
inlinestatic |
Gets the heap_no of the smallest user record on a page.
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.
The string should not be free()'d or modified. This functions is a bit complex for following reasons:
lock | in: lock |
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.
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.
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.
The string should not be free()'d or modified.
lock | in: lock |
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 |
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 |
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. in: copy of the old, not reorganized 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 |
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 |
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) |
void lock_rec_discard | ( | lock_t * | in_lock | ) |
Removes a record lock request, waiting or granted, from the queue.
in: record lock object: all record locks which are contained in this lock object are removed
[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 |
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. in: page to be 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 |
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.
The string should not be free()'d or modified.
lock | in: lock |
For a record lock, gets the tablespace number and page number on which the lock is.
|
inlinestatic |
Calculates the hash value of a page file address: used in inserting or searching for a lock in the hash table or getting global shard index.
page_id | specifies the page |
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.
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 |
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 |
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 in such an update moved, 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. in: record whose lock state is stored on the infimum record of the same page; lock bits are reset on the 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.
in: LOCK_S or LOCK_X
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 |
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. in: also removes table S and X locks
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 |
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() |
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.
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 |
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.
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 |
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.
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 |
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 |
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. in/out: transaction
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). in/out: transaction
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. in: root page
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 |
bool lock_validate | ( | ) |
Validates the lock system.
|
inlinestatic |
Acquire the lock_sys->wait_mutex.
|
inlinestatic |
Release the lock_sys->wait_mutex.
|
inlinestatic |
Test if lock_sys->wait_mutex is owned.
void lock_wait_request_check_for_cycles | ( | ) |
Notifies the thread which analyzes wait-for-graph that there was at least one new edge added or modified ( trx->blocking_trx has changed ), so that the thread will know it has to analyze it.
void lock_wait_suspend_thread | ( | que_thr_t * | thr | ) |
Puts a user OS thread to wait for a lock to be released.
If an error occurs during the wait trx->error_state associated with thr is != DB_SUCCESS when we return. DB_INTERRUPTED, DB_LOCK_WAIT_TIMEOUT and DB_DEADLOCK are possible errors. DB_DEADLOCK is returned if selective deadlock resolution chose this transaction as a victim. in: query thread associated with the user OS thread
void lock_wait_timeout_thread | ( | ) |
A thread which wakes up threads whose lock wait may have lasted too long.
A thread which wakes up threads whose lock wait may have lasted too long.
The last time we've checked for timeouts.
|
extern |
|
constexpr |
when this bit is set, it means that the lock holds only on the gap before the record; for instance, an x-lock on the gap does not give permission to modify the record on which the bit is set; locks of this type are created when records are removed from the index chain of records
|
constexpr |
this bit is set when we place a waiting gap type record lock request in order to let an insert of an index record to wait until there are no conflicting locks by other transactions on the gap; note that this flag remains set when the waiting lock is granted, or if the lock is inherited to a neighboring record
|
constexpr |
Lock modes and types.
mask used to extract mode from the type_mode field in a lock
|
constexpr |
this flag denotes an ordinary next-key lock in contrast to LOCK_GAP or LOCK_REC_NOT_GAP
|
constexpr |
Page lock.
|
constexpr |
Predicate lock.
|
constexpr |
record lock
|
constexpr |
this bit means that the lock is only on the index record and does NOT block inserts to the gap before the index record; this is used in the case when we retrieve a record with a unique key, and is also used in locking plain SELECTs (not part of UPDATE or DELETE) when the user has set the READ COMMITTED isolation level
|
extern |
The lock system.
|
constexpr |
Lock types.
table lock
|
constexpr |
mask used to extract lock type from the type_mode field in a lock
|
constexpr |
Waiting lock flag; when set, it means that the lock has not yet been granted, it is just waiting for its turn in the wait queue.