MySQL 8.4.3
Source Code Documentation
|
Context of the owner of metadata locks. More...
#include <mdl.h>
Public Types | |
typedef I_P_List< MDL_ticket, I_P_List_adapter< MDL_ticket, &MDL_ticket::next_in_context, &MDL_ticket::prev_in_context > > | Ticket_list |
typedef Ticket_list::Iterator | Ticket_iterator |
Public Member Functions | |
MDL_context () | |
Initialize a metadata locking context. More... | |
void | destroy () |
Destroy metadata locking context. More... | |
bool | try_acquire_lock (MDL_request *mdl_request) |
Try to acquire one lock. More... | |
bool | acquire_lock (MDL_request *mdl_request, Timeout_type lock_wait_timeout) |
Acquire one lock with waiting for conflicting locks to go away if needed. More... | |
bool | acquire_locks (MDL_request_list *requests, Timeout_type lock_wait_timeout) |
Acquire exclusive locks. More... | |
bool | upgrade_shared_lock (MDL_ticket *mdl_ticket, enum_mdl_type new_type, Timeout_type lock_wait_timeout) |
Upgrade a shared metadata lock. More... | |
bool | clone_ticket (MDL_request *mdl_request) |
Create a copy of a granted ticket. More... | |
bool | clone_tickets (const MDL_context *ticket_owner, enum_mdl_duration duration) |
Create copy of all granted tickets of particular duration from given context to current context. More... | |
void | release_all_locks_for_name (MDL_ticket *ticket) |
Release all explicit locks in the context which correspond to the same name/object as this lock request. More... | |
void | release_locks (MDL_release_locks_visitor *visitor) |
Release all explicit locks in the context for which the release() method of the provided visitor evalates to true. More... | |
void | release_lock (MDL_ticket *ticket) |
Release lock with explicit duration. More... | |
bool | owns_equal_or_stronger_lock (const MDL_key *mdl_key, enum_mdl_type mdl_type) |
Auxiliary function which allows to check if we have some kind of lock on a object. More... | |
bool | owns_equal_or_stronger_lock (MDL_key::enum_mdl_namespace mdl_namespace, const char *db, const char *name, enum_mdl_type mdl_type) |
Auxiliary function which allows to check if we have some kind of lock on a object. More... | |
bool | find_lock_owner (const MDL_key *mdl_key, MDL_context_visitor *visitor) |
Find the first context which owns the lock and inspect it by calling MDL_context_visitor::visit_context() method. More... | |
bool | has_lock (const MDL_savepoint &mdl_savepoint, MDL_ticket *mdl_ticket) |
Does this savepoint have this lock? More... | |
bool | has_locks () const |
bool | has_locks (MDL_key::enum_mdl_namespace mdl_namespace) const |
Does this context have an lock of the given namespace? More... | |
bool | has_locks_waited_for () const |
Do we hold any locks which are possibly being waited for by another MDL_context? More... | |
bool | has_locks (enum_mdl_duration duration) |
MDL_savepoint | mdl_savepoint () |
void | set_explicit_duration_for_all_locks () |
Set explicit duration for all locks in the context. More... | |
void | set_transaction_duration_for_all_locks () |
Set transactional duration for all locks in the context. More... | |
void | set_lock_duration (MDL_ticket *mdl_ticket, enum_mdl_duration duration) |
Change lock duration for transactional lock. More... | |
void | release_statement_locks () |
void | release_transactional_locks () |
Release locks acquired by normal statements (SELECT, UPDATE, DELETE, etc) in the course of a transaction. More... | |
void | rollback_to_savepoint (const MDL_savepoint &mdl_savepoint) |
Releases metadata locks that were acquired after a specific savepoint. More... | |
MDL_context_owner * | get_owner () const |
uint | get_deadlock_weight () const |
void | init (MDL_context_owner *arg) |
void | set_needs_thr_lock_abort (bool needs_thr_lock_abort) |
bool | get_needs_thr_lock_abort () const |
void | set_force_dml_deadlock_weight (bool force_dml_deadlock_weight) |
uint | get_random () |
Get pseudo random value in [0 . More... | |
THD * | get_thd () const |
Within MDL subsystem this one is only used for DEBUG_SYNC. More... | |
void | find_deadlock () |
Try to find a deadlock. More... | |
bool | visit_subgraph (MDL_wait_for_graph_visitor *dvisitor) |
A fragment of recursive traversal of the wait-for graph of MDL contexts in the server in search for deadlocks. More... | |
void | will_wait_for (MDL_wait_for_subgraph *waiting_for_arg) |
Inform the deadlock detector there is an edge in the wait-for graph. More... | |
void | done_waiting_for () |
Remove the wait-for edge from the graph after we're done waiting. More... | |
void | lock_deadlock_victim () |
void | unlock_deadlock_victim () |
Public Attributes | |
MDL_wait | m_wait |
If our request for a lock is scheduled, or aborted by the deadlock detector, the result is recorded in this class. More... | |
Private Member Functions | |
MDL_ticket * | find_ticket (MDL_request *mdl_req, enum_mdl_duration *duration) |
Check whether the context already holds a compatible lock ticket on an object. More... | |
void | release_locks_stored_before (enum_mdl_duration duration, MDL_ticket *sentinel) |
Release all locks associated with the context. More... | |
void | release_lock (enum_mdl_duration duration, MDL_ticket *ticket) |
Release lock. More... | |
bool | try_acquire_lock_impl (MDL_request *mdl_request, MDL_ticket **out_ticket) |
Auxiliary method for acquiring lock without waiting. More... | |
void | materialize_fast_path_locks () |
"Materialize" requests for locks which were satisfied using "fast path" by properly including them into corresponding MDL_lock::m_granted bitmaps/lists and removing it from packed counter in MDL_lock::m_fast_path_state. More... | |
bool | fix_pins () |
Allocate pins which are necessary to work with MDL_map container if they are not allocated already. More... | |
MDL_context (const MDL_context &rhs) | |
MDL_context & | operator= (MDL_context &rhs) |
Private Attributes | |
MDL_ticket_store | m_ticket_store |
Lists of all MDL tickets acquired by this connection. More... | |
MDL_context_owner * | m_owner |
bool | m_needs_thr_lock_abort |
true - if for this context we will break protocol and try to acquire table-level locks while having only S lock on some table. More... | |
bool | m_force_dml_deadlock_weight |
Indicates that we need to use DEADLOCK_WEIGHT_DML deadlock weight for this context and ignore the deadlock weight provided by the MDL_wait_for_subgraph object which we are waiting for. More... | |
mysql_prlock_t | m_LOCK_waiting_for |
Read-write lock protecting m_waiting_for member. More... | |
MDL_wait_for_subgraph * | m_waiting_for |
Tell the deadlock detector what metadata lock or table definition cache entry this session is waiting for. More... | |
LF_PINS * | m_pins |
Thread's pins (a.k.a. More... | |
uint | m_rand_state |
State for pseudo random numbers generator (PRNG) which output is used to perform random dives into MDL_lock objects hash when searching for unused objects to free. More... | |
Friends | |
bool | mdl_unittest::test_drive_fix_pins (MDL_context *) |
Context of the owner of metadata locks.
I.e. each server connection has such a context.
typedef I_P_List<MDL_ticket, I_P_List_adapter<MDL_ticket, &MDL_ticket::next_in_context, &MDL_ticket::prev_in_context> > MDL_context::Ticket_list |
MDL_context::MDL_context | ( | ) |
Initialize a metadata locking context.
This is to be called when a new server connection is created.
|
private |
bool MDL_context::acquire_lock | ( | MDL_request * | mdl_request, |
Timeout_type | lock_wait_timeout | ||
) |
Acquire one lock with waiting for conflicting locks to go away if needed.
[in,out] | mdl_request | Lock request object for lock to be acquired |
lock_wait_timeout | Seconds to wait before timeout. |
false | Success. MDL_request::ticket points to the ticket for the lock. |
true | Failure (Out of resources or waiting is aborted), |
bool MDL_context::acquire_locks | ( | MDL_request_list * | mdl_requests, |
Timeout_type | lock_wait_timeout | ||
) |
Acquire exclusive locks.
There must be no granted locks in the context.
This is a replacement of lock_table_names(). It is used in RENAME, DROP and other DDL SQL statements.
mdl_requests | List of requests for locks to be acquired. |
lock_wait_timeout | Seconds to wait before timeout. |
false | Success |
true | Failure |
bool MDL_context::clone_ticket | ( | MDL_request * | mdl_request | ) |
Create a copy of a granted ticket.
This is used to make sure that HANDLER ticket is never shared with a ticket that belongs to a transaction, so that when we HANDLER CLOSE, we don't release a transactional ticket, and vice versa – when we COMMIT, we don't mistakenly release a ticket for an open HANDLER.
true | An error occurred. |
false | Success. |
bool MDL_context::clone_tickets | ( | const MDL_context * | ticket_owner, |
enum_mdl_duration | duration | ||
) |
Create copy of all granted tickets of particular duration from given context to current context.
Used by XA for preserving locks during client disconnect.
ticket_owner | Owner of tickets to be cloned |
duration | MDL lock duration for that tickets are to be cloned |
true | Out of memory or deadlock happened or lock request was refused by storage engine. |
false | Success. |
void MDL_context::destroy | ( | ) |
Destroy metadata locking context.
Assumes and asserts that there are no active or pending locks associated with this context at the time of the destruction.
Currently does nothing. Asserts that there are no pending or satisfied lock requests. The pending locks must be released prior to destruction. This is a new way to express the assertion that all tables are closed before a connection is destroyed.
|
inline |
Remove the wait-for edge from the graph after we're done waiting.
void MDL_context::find_deadlock | ( | ) |
Try to find a deadlock.
This function produces no errors.
bool MDL_context::find_lock_owner | ( | const MDL_key * | mdl_key, |
MDL_context_visitor * | visitor | ||
) |
Find the first context which owns the lock and inspect it by calling MDL_context_visitor::visit_context() method.
|
private |
Check whether the context already holds a compatible lock ticket on an object.
Start searching from list of locks for the same duration as lock being requested. If not look at lists for other durations.
mdl_request | Lock request object for lock to be acquired | |
[out] | result_duration | Duration of lock which was found. |
|
private |
Allocate pins which are necessary to work with MDL_map container if they are not allocated already.
|
inline |
|
inline |
|
inline |
|
inline |
Get pseudo random value in [0 .
. 2^31-1] range.
|
inline |
Within MDL subsystem this one is only used for DEBUG_SYNC.
Do not use it to peek/poke into other parts of THD from MDL.
bool MDL_context::has_lock | ( | const MDL_savepoint & | mdl_savepoint, |
MDL_ticket * | mdl_ticket | ||
) |
Does this savepoint have this lock?
true | The ticket is older than the savepoint or is an LT, HA or GLR ticket. Thus it belongs to the savepoint or has explicit duration. |
false | The ticket is newer than the savepoint. and is not an LT, HA or GLR ticket. |
|
inline |
|
inline |
bool MDL_context::has_locks | ( | MDL_key::enum_mdl_namespace | mdl_namespace | ) | const |
Does this context have an lock of the given namespace?
true | At least one lock of given namespace held |
false | No locks of the given namespace held |
bool MDL_context::has_locks_waited_for | ( | ) | const |
Do we hold any locks which are possibly being waited for by another MDL_context?
true | A lock being 'waited_for' was found. |
false | No one waits for the lock(s) we hold. |
|
inline |
|
inline |
|
private |
"Materialize" requests for locks which were satisfied using "fast path" by properly including them into corresponding MDL_lock::m_granted bitmaps/lists and removing it from packed counter in MDL_lock::m_fast_path_state.
|
inline |
|
private |
bool MDL_context::owns_equal_or_stronger_lock | ( | const MDL_key * | mdl_key, |
enum_mdl_type | mdl_type | ||
) |
Auxiliary function which allows to check if we have some kind of lock on a object.
Returns true if we have a lock of an equal to given or stronger type.
mdl_key | Key to check for ownership |
mdl_type | Lock type. Pass in the weakest type to find out if there is at least some lock. |
bool MDL_context::owns_equal_or_stronger_lock | ( | MDL_key::enum_mdl_namespace | mdl_namespace, |
const char * | db, | ||
const char * | name, | ||
enum_mdl_type | mdl_type | ||
) |
Auxiliary function which allows to check if we have some kind of lock on a object.
Returns TRUE if we have a lock of an equal to given or stronger type.
mdl_namespace | Id of object namespace |
db | Name of the database |
name | Name of the object |
mdl_type | Lock type. Pass in the weakest type to find out if there is at least some lock. |
void MDL_context::release_all_locks_for_name | ( | MDL_ticket * | name | ) |
Release all explicit locks in the context which correspond to the same name/object as this lock request.
name | One of the locks for the name/object for which all locks should be released. |
|
private |
Release lock.
duration | Lock duration. |
ticket | Ticket for lock to be released. |
void MDL_context::release_lock | ( | MDL_ticket * | ticket | ) |
Release lock with explicit duration.
ticket | Ticket for lock to be released. |
void MDL_context::release_locks | ( | MDL_release_locks_visitor * | visitor | ) |
Release all explicit locks in the context for which the release() method of the provided visitor evalates to true.
visitor | Object to ask if the lock should be released. |
|
private |
Release all locks associated with the context.
If the sentinel is not NULL, do not release locks stored in the list after and including the sentinel.
Statement and transactional locks are added to the beginning of the corresponding lists, i.e. stored in reverse temporal order. This allows to employ this function to:
void MDL_context::release_statement_locks | ( | ) |
void MDL_context::release_transactional_locks | ( | ) |
Release locks acquired by normal statements (SELECT, UPDATE, DELETE, etc) in the course of a transaction.
Do not release HANDLER locks, if there are any.
This method is used at the end of a transaction, in implementation of COMMIT (implicit or explicit) and ROLLBACK.
void MDL_context::rollback_to_savepoint | ( | const MDL_savepoint & | mdl_savepoint | ) |
Releases metadata locks that were acquired after a specific savepoint.
void MDL_context::set_explicit_duration_for_all_locks | ( | ) |
Set explicit duration for all locks in the context.
|
inline |
void MDL_context::set_lock_duration | ( | MDL_ticket * | mdl_ticket, |
enum_mdl_duration | duration | ||
) |
Change lock duration for transactional lock.
mdl_ticket | Ticket representing lock. |
duration | Lock duration to be set. |
|
inline |
void MDL_context::set_transaction_duration_for_all_locks | ( | ) |
Set transactional duration for all locks in the context.
bool MDL_context::try_acquire_lock | ( | MDL_request * | mdl_request | ) |
Try to acquire one lock.
Unlike exclusive locks, shared locks are acquired one by one. This is interface is chosen to simplify introduction of the new locking API to the system. MDL_context::try_acquire_lock() is currently used from open_table(), and there we have only one table to work with.
This function may also be used to try to acquire an exclusive lock on a destination table, by ALTER TABLE ... RENAME.
Returns immediately without any side effect if encounters a lock conflict. Otherwise takes the lock.
[in,out] | mdl_request | Lock request object for lock to be acquired |
false | Success. The lock may have not been acquired. Check the ticket, if it's NULL, a conflicting lock exists. |
true | Out of resources, an error has been reported. |
|
private |
Auxiliary method for acquiring lock without waiting.
[in,out] | mdl_request | Lock request object for lock to be acquired |
[out] | out_ticket | Ticket for the request in case when lock has not been acquired. |
false | Success. The lock may have not been acquired. Check MDL_request::ticket, if it's NULL, a conflicting lock exists. In this case "out_ticket" out parameter points to ticket which was constructed for the request. MDL_ticket::m_lock points to the corresponding MDL_lock object and MDL_lock::m_rwlock write-locked. |
true | Out of resources, an error has been reported. |
|
inline |
bool MDL_context::upgrade_shared_lock | ( | MDL_ticket * | mdl_ticket, |
enum_mdl_type | new_type, | ||
Timeout_type | lock_wait_timeout | ||
) |
Upgrade a shared metadata lock.
Used in ALTER TABLE and CREATE TABLE.
mdl_ticket | Lock to upgrade. |
new_type | Lock type to upgrade to. |
lock_wait_timeout | Seconds to wait before timeout. |
false | Success |
true | Failure (thread was killed) |
bool MDL_context::visit_subgraph | ( | MDL_wait_for_graph_visitor * | gvisitor | ) |
A fragment of recursive traversal of the wait-for graph of MDL contexts in the server in search for deadlocks.
Assume this MDL context is a node in the wait-for graph, and direct the visitor to all adjacent nodes. As long as the starting node is remembered in the visitor, a deadlock is found when the same node is visited twice. One MDL context is connected to another in the wait-for graph if it waits on a resource that is held by the other context.
true | A deadlock is found. A pointer to deadlock victim is saved in the visitor. |
false | TBD |
|
inline |
Inform the deadlock detector there is an edge in the wait-for graph.
|
friend |
|
private |
Indicates that we need to use DEADLOCK_WEIGHT_DML deadlock weight for this context and ignore the deadlock weight provided by the MDL_wait_for_subgraph object which we are waiting for.
|
private |
Read-write lock protecting m_waiting_for member.
|
private |
true - if for this context we will break protocol and try to acquire table-level locks while having only S lock on some table.
To avoid deadlocks which might occur during concurrent upgrade of SNRW lock on such object to X lock we have to abort waits for table-level locks for such connections. false - Otherwise.
|
private |
|
private |
Thread's pins (a.k.a.
hazard pointers) to be used by lock-free implementation of MDL_map::m_locks container. NULL if pins are not yet allocated from container's pinbox.
|
private |
State for pseudo random numbers generator (PRNG) which output is used to perform random dives into MDL_lock objects hash when searching for unused objects to free.
|
private |
Lists of all MDL tickets acquired by this connection.
The entire set of locks acquired by a connection can be separated in three subsets according to their duration: locks released at the end of statement, at the end of transaction and locks are released explicitly.
Statement and transactional locks are locks with automatic scope. They are accumulated in the course of a transaction, and released either at the end of uppermost statement (for statement locks) or on COMMIT, ROLLBACK or ROLLBACK TO SAVEPOINT (for transactional locks). They must not be (and never are) released manually, i.e. with release_lock() call.
Tickets with explicit duration are taken for locks that span multiple transactions or savepoints. These are: HANDLER SQL locks (HANDLER SQL is transaction-agnostic), LOCK TABLES locks (you can COMMIT/etc under LOCK TABLES, and the locked tables stay locked), user level locks (GET_LOCK()/RELEASE_LOCK() functions) and locks implementing "global read lock".
Statement/transactional locks are always prepended to the beginning of the appropriate list. In other words, they are stored in reverse temporal order. Thus, when we rollback to a savepoint, we start popping and releasing tickets from the front until we reach the last ticket acquired after the savepoint.
Locks with explicit duration are not stored in any particular order, and among each other can be split into four sets:
MDL_wait MDL_context::m_wait |
If our request for a lock is scheduled, or aborted by the deadlock detector, the result is recorded in this class.
|
private |
Tell the deadlock detector what metadata lock or table definition cache entry this session is waiting for.
In principle, this is redundant, as information can be found by inspecting waiting queues, but we'd very much like it to be readily available to the wait-for graph iterator.