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, 2024, Oracle Corporation and/or its affiliates. All rights reserved.