WL#7567: Handlerton MDL callback
Affects: Server-5.7
—
Status: Complete
Implement support for the server to be used for DDL statements in a configuration where objects(tables, triggers and so forth) are shared between servers, extending the metadata locking to cover DDL statements in sessions also on other servers which share the same objects. Since objects shared between servers in MySQL are implemented in the storage engine layer, the storage engine plugin(s) must be involved to allow statements in sessions on other servers to be locked or unlocked. Quoted from https://dev.mysql.com/doc/refman/5.6/en/metadata-locking.html: "MySQL uses metadata locking to manage access to objects (tables, triggers, and so forth). Metadata locking is used to ensure data consistency ..." "To ensure transaction serializability, the server must not permit one session to perform a data definition language (DDL) statement on a table that is used in an uncompleted explicitly or implicitly started transaction in another session. The server achieves this by acquiring metadata locks on tables used within a transaction and deferring release of those locks until the transaction ends. A metadata lock on a table prevents changes to the table's structure. This locking approach has the implication that a table that is being used by a transaction within one session cannot be used in DDL statements by other sessions until the transaction ends." This worklog describes how it should be possible for individual storage engine plugin(s) to hook into the metadata locking in order to implement support for ensuring that the metadata of the same object may not be modified in more than one server at a time. To limit the scope and impact of this feature each server should maintain it's own state in regards to metadata locking and only when a lock which allows changes to metadata(ie. exclusive lock) there is a need to involve the storage engine plugin(s). When the server detects that metadata is to be changed by a DDL statement it need to involve the storage engine plugin(s) allowing them to ensure that it's not allowed to change the metadata of other servers in the same configuration. This should be done in such a way that concurrent DML or DDL statements on other objects are not prevented. User Documentation ================== New Performance Schema lock status documented here: http://dev.mysql.com/doc/refman/5.7/en/metadata-locks-table.html
F-1: The storage engine plugin (hereafter called handlerton) must be
notified before metadata lock allowing metadata to be changed,
i.e. exclusive lock, is taken on an object. The handlerton
must also be notified about start of ALTER TABLE statement,
which might be expensive to abort at the stage when it
acquires exclusive metadata lock.
F-1.1: The handlerton should be notified about such lock requests for
the following types of objects: TABLE, FUNCTION, PROCEDURE,
TRIGGER, EVENT, SCHEMA and TABLESPACE.
F-1.2: Information making it possible to determine the type of object
and it's name should be made available.
F-1.3: The handlerton should be able to decide whether or not locking of
the requested object (or starting ALTER TABLE on the table)
is currently allowed or not. When the handlerton decides that
locking is not allowed the statement should fail with an error,
similarly to other scenarios in which metadata locking fails
without handlerton involvement.
New error code and message to be introduced for this purpose.
F-1.4: The handlerton should be reponsible to interpret any errors
which occurs while it tries to lock on other servers. Depending
on error and handlerton settings, it should decide wheter or
not to allow lock.
F-1.5: It should be possible for the handlerton to push warnings
describing status of the lock operation.
F-2: The handlerton must be notified after metadata lock allowing
metadata to be changed is released. The handlerton also must
be notified about end of ALTER TABLE statement execution.
F-2.1: Information making it possible to determine the type of object
and it's name should be made available.
F-2.2: It should be possible for the handlerton to push warnings
indicating status of the unlock operation.
F-2.3: There is no need to try and handle errors from the handlerton
unlock operation. Should an error occur, processing should
continue and the next handlerton(if any) should be unlocked.
F-3: While taking or releasing handlerton lock the server should
not prevent concurrent DML or DDL statements on other objects.
This is to allow the handlerton to perform any possible action
(like waiting on locks, disk reads or network communication)
while handling the lock/unlock request.
F-4: The handlerton does not need to be involved if the object to be
changed is temporary(since such objects are only visible in one
server).
F-5: All the metadata locks where the handlerton is involved should
be visible and identifiable in P_S.METADATA_LOCKS table if
instrumentation for metadata locks is enabled. This will make
it possible to verify the functionality as well as diagnose
potential problems.
F-6: In order to avoid potential locking conflicts the order of
involving the handlerton and performing the metadata lock in
the server must be consistent and the handlerton need to
always be involved first when taking lock and last when releasing
lock.
Rationale for additional notification in case of ALTER TABLE
------------------------------------------------------------
Since in case of ALTER TABLE statement upgrade to exclusive metadata
lock happens late in the process of statement execution it is going
to be expensive to abort statement execution as result of failed
SE notification at this point. To alleviate this issue we are going
to additionally notify handlerton at the start of ALTER TABLE
on base table and at its end. This will give SE chance to abort
execution of ALTER TABLE early in the process without wasting
precious resources.
Changes to SE API
-----------------
Two new function pointers are to be added to handlerton struct.
Engines which are interested in notifications about acquire/release
of exclusive metadata lock and about start/end of ALTER TABLE
need to initialize these members to point to notification functions.
Also enum allowing to differentiate pre-event notification calls
from post-event notification calls will be added.
enum ha_notification_type { HA_NOTIFY_PRE_EVENT, HA_NOTIFY_POST_EVENT };
struct handlerton {
...
/**
Notify/get permission from storage engine before acquisition or after
release of exclusive metadata lock on object represented by key.
@param thd Thread context.
@param mdl_key MDL key identifying object on which exclusive
lock is to be acquired/was released.
@param notification_type Indicates whether this is pre-acquire or
post-release notification.
@note Notification is done only for objects from TABLESPACE, SCHEMA,
TABLE, FUNCTION, PROCEDURE, TRIGGER and EVENT namespaces.
@note Problems during notification are to be reported as warnings, MDL
subsystem will report generic error if pre-acquire notification
fails/SE refuses lock acquisition.
@note Return value is ignored/error is not reported in case of
post-release notification.
@note In some cases post-release notification might happen when
there were no prior pre-acquire notification. For example,
when SE was loaded after exclusive lock acquisition, or when
we need notify SEs which permitted lock acquisition that it
didn't happen because one of SEs didn't allow it (in such case
we will do post-release notification for all SEs for simplicity).
@return False - if notification was successful/lock can be acquired,
True - if it has failed/lock should not be acquired.
*/
bool (*notify_exclusive_mdl)(THD *thd, const MDL_key *mdl_key,
ha_notification_type notification_type);
/**
Notify/get permission from storage engine before or after execution of
ALTER TABLE operation on the table identified by the MDL key.
@param thd Thread context.
@param mdl_key MDL key identifying table which is going to be
or was ALTERed.
@param notification_type Indicates whether this is pre-ALTER TABLE or
post-ALTER TABLE notification.
@note This hook is necessary because for ALTER TABLE upgrade to X
metadata lock happens fairly late during the execution process,
so it can be expensive to abort ALTER TABLE operation at this
stage by returning failure from notify_exclusive_mdl() hook.
@note This hook follows the same error reporting convention as
@see notify_exclusive_mdl().
@note Similarly to notify_exclusive_mdl() in some cases post-ALTER
notification might happen even if there were no prior pre-ALTER
notification.
@note Post-ALTER notification can happen before post-release notification
for exclusive metadata lock acquired by this ALTER TABLE.
@return False - if notification was successful/ALTER TABLE can be proceed.
True - if it has failed/ALTER TABLE should be aborted.
*/
bool (*notify_alter_table)(THD *thd, const MDL_key *mdl_key,
ha_notification_type notification_type);
...
};
We will also add the following two helper functions to handler.h:
bool ha_notify_exclusive_mdl(THD *thd, const MDL_key *mdl_key,
ha_notification_type notification_type);
bool ha_notify_alter_table(THD *thd, const MDL_key *mdl_key,
ha_notification_type notification_type);
These functions are to be used by SQL-layer to notify ALL interested
(i.e. implementing the above calls) SEs about respective events.
Changes to MDL subsystem and SQL-layer
--------------------------------------
Code in MDL subsystem is to be extended to call ha_notify_exclusive_mdl(...,
HA_NOTIFY_PRE_EVENT) each time we are about to acquire or upgrade to X metadata
lock. If one of SEs refuses lock acquisition MDL subsystem will report
ER_LOCK_REFUSED_BY_ENGINE error.
We will call ha_notify_exclusive_mdl(..., HA_NOTIFY_POST_EVENT) after releasing
or downgrading from X lock. We will also do post-release notification
in cases when we have successfully done pre-acquire notification but
then failed to acquire X metadata lock for some reason. Errors during
post-release notification are ignored.
Similar changes are to be done to ALTER TABLE implementation.
Error message
-------------
New ER_LOCK_REFUSED_BY_ENGINE error and corresponding error message is added.
P_S integration
---------------
It is responsibility of SE to change connection status and PSI stage if
its implementation of notification hook is going to wait for some resource
or perform some long operation. MDL subsystem or ALTER TABLE implementation
won't do anything about this (as they don't know if notification will
involve waiting or not).
Pre-acquire notification and post-release phases in metadata lock
acquisition/release cycle will be reflected by new values in
P_S.METADATA_LOCKS.STATUS column. We will use "PRE_ACQUIRE_NOTIFY"
and "POST_RELEASE_NOTIFY" statuses for pre-acquire and post-release
phases correspondingly. It is responsibility of MDL subsystem to
notify P_S instrumentation about entering/leaving these phases.
Performance considerations
--------------------------
Since notification on exclusive metadata lock acquisition (and ALTER
TABLE notification) will be done only during DDL execution decrease in
performance/scalability caused by such notification (e.g. due to fact
that we acquire LOCK_plugin for it) should not be a concern.
Copyright (c) 2000, 2025, Oracle Corporation and/or its affiliates. All rights reserved.