WL#3574: Online backup: Service API for Metadata Objects II
Affects: Server-6.0
—
Status: Complete
Rationale --------- To make a alpha-quality interface between server kernel and backup kernel. Stabilizing this interface is WL#4264. Overview -------- The online backup system requires server functionality to permit the access to metadata concerning database objects (e.g., CREATE DATABASE). This functionality is not unique to online backup and therefore shall be designed to support access to metadata using a generalized interface. Background ---------- One of the driving goals of the online backup system is to minimize reliance on functionality in the MySQL server proper. That is, to abstract the backup code from the server code as much as possible in order to avoid conditions where changes in one breaks the other. While a complete abstraction is not possible (the backup code needs to communicate with the server in a variety of ways), it is possible to isolate the affects of changes to either the online backup or server code by using an intermediate layer. The term "service interface" has been given to this layer to indicate its goal: to provide a buffer between the services needed by online backup and how those services are provided by the server. Requirements ------------ The purpose of this worklog is to establish a service interface that can be used to gather metadata about database objects, iterate through the various types of objects supported, and to create database objects on restore. The deliverable for this worklog is a service interface that implements these features (at a minimum) for the following database objects. * Trigger (WL#3582) [40] * View [37] * Stored Procedure [38] * Stored Function [39] * Event [41] Note: The [] references a number assigned to each object described in WL#3713. There is a complete list of objects described in WL#3713.
The service interface shall be designed to allow the following operations concerning metadata. * The retrieval of metadata concerning a specific object. * The recreation of a specific object using the retrieved metadata. * Enumeration for each object supported and for all objects of a given type. * Abstractions of the DDL blocker to permit isolation of DDL blocker. * Dependency checking for objects to discover objects that need to be created/exist before a given object is created. The service interface shall be designed using abstractions to represent the above functionality. The retrieval of metadata shall be called 'serialize' and the output of the serialize() method called the serialization of the object. The serialization of the object can be used to create an instance of the service interface class and this process shall be called materialize. The process of using the materialized serialization and creating a new object on the server shall be referred as executing the serialization. Thus, an object can be serialized for storage in the online backup and materialized on restore and the serialization executed to create the database object on the server. For example, the serialization, e.g. db->serialize() of a database shall produce a serialization that can be stored in the online backup image file. Upon restore, the service interface can be used to materialize this data using db->materialize(serialized_data). To create the object on the server (to create the database), the service interface would allow db->execute() to create the database 'xyz'. All other objects supported in this worklog shall use this mechanism. Architecture ------------ The high-level architecture is given in the following diagram. +-----------+ +---------------+ || | online backup | |-----------+ +---------------+ | | | | +--------+----------+ | | +--------+----------+ | service interface | +--------+----------+ | | +-------+---------+ | server (mysqld) | +-------+---------+ This diagram illustrates that the service interface provides an abstraction of server functionality for calling applications such as mysqldump or online backup. The advantage is that the server interface can be used to isolate changes to the server from the applications and vice-versa. Furthermore, the service interface can be improved independently of either caller or callee. Decision -------- A decision was made to serialize the object metadata using the currently available show_create_* methods. This implementation of the serialization shall produce a string obtained in the same way as in SHOW CREATE statements. However, there is a problem related to the fact that output of SHOW CRATE statement depends on the setting of sql_mode variable (see BUG#33570 and BUG#33571). If the mode is anything else than the "native" mysql mode then CREATE statements can miss some important clauses (like "ENGINE=xxx" for a table). Also, when object is re-created using the full CREATE statement for it, sql_mode must be set to "native" as otherwise not all clauses will be understood by the server. All this must be taken into account when implementing serialization via CREATE statements. Note: In the future, the serialization may not be based on CREATE statements and therefore the caller of the service interface should make no assumptions about the content of the serialization other than what has been stated in the above sections. Known Limitation ---------------- When objects are described by CREATE statements, they are created by executing these statements. Currently this is done by passing CREATE statement to mysql_parse() function. However, this function can not be called from inside a stored routine - if it happens, an assertion is violated and server crashes (see BUG#33563). Therefore, it has been decided to not permit the inclusion of the BACKUP or RESTORE command inside a stored routing. See solution for BUG#33563 for more details. Future Work ----------- It has been suggested that the ownership of the service interface could be the runtime team. If ownership of this interface is transferred to the runtime team, it is requested that they refactor the implementation of the service interface however they see fit. It was suggested that the serialize/materialize/execute mechanism is sufficient to allow the implementation to be changed to use something other than CREATE SQL statements. In such a case, the design shall incorporate a mechanism to allow identification of versions of the service interface. It has been decided to leave out the complete implementation of dependency checking for views and other objects. Additional work is needed to understand all of the requirements for dependency checking WRT backup and restore. See WL#4211 and WL#4225.
The service interface shall be implemented in the ./sql source folder and named si_objects.*. These source files shall comprise the interface specification and code for the following requirements. Object Class ------------ The service interface shall implement a general object class named Obj. This class shall have, at a minimum, the following methods. This shall become an abstract class from which each database object support (trigger, event, etc.) shall derive. class Obj { public: virtual bool serialize(THD *thd, String *serialialization) = 0; virtual const String *get_name() = 0; virtual const String *get_db_name() = 0; virtual bool execute(THD *thd) = 0; virtual ~Obj() { } private: virtual bool materialize(uint serialization_version, const String *serialialization) = 0; virtual bool drop(THD *thd) = 0; }; In addition to the serialize(), materialize(), and execute() methods discussed in the high level specification, the methods get_name() and get_db_name() are provided to allow identification of the object instance. The method drop() is included to permit a general call to destroy an object on the server. For example to drop a database, a child class could be materialized for the database then drop() can be called to execute DROP DATABASE ... on the server. The serialization mechanism shall be implemented to support versioning of the interface. The initial version shall be 0 and it shall not be considered in future revisions for backward compatibility. The reason is version 0 implements serialization using CREATE commands which may not be the best implementation for future plans for the server. Thus, starting with version 1, the service interface shall require the version number present when services are requested and shall provide backward compatibility in future versions of the service interface. Iterators --------- The iterators for the database objects shall be a simple class that permits the instantiation of the iterator and a forward-only increment mechanism. The abstract class for the iterator functionality is shown below. class ObjIterator { public: ObjIterator() { } virtual Obj *next() = 0; public: virtual ~ObjIterator() { } }; Versioning of Service Interface ------------------------------- The service interface shall use as its versioning the version number of the server. When a caller uses the serialization mechanism, she must record the version number of the server and store it with the serialization data. Upon materialization, the caller passes the version number in the method call as shown. materialize(uint serialization_version, const String *serialialization); This way, the service interface shall be capable of supporting services for multiple releases. Note that the first release of this interface shall use 0 in place of the version number as described above. Convenience Methods ------------------- The service interface shall implement convenience methods to reduce the burden of the caller to create instances of objects, iterators, and materialization. A method for each database object supported shall be created to allow the instantiation of a single object shall be provided using the following or similar method. Obj *get_database(const String *db_name); A method for each database object supported shall be created to allow the creation of an object iterator. For example, to get an iterator for all of the databases on a server, the service interface shall implement the following or similar method. ObjIterator *get_databases(THD *thd); A method for each database object supported shall be created to allow the materialization of a single object. The following or similar method shall be implemented. Obj *materialize_database(const String *db_name, uint serialization_version, const String *serialialization); DDL Blocker ----------- The following methods shall be implemented to abstract the DDL blocker methods already implemented in the server. These methods are necessary to allow the replacement of the DDL blocker code in the future without affecting the code in the caller. bool ddl_blocker_enable(THD *thd); void ddl_blocker_disable(); void ddl_blocker_exception_on(THD *thd); void ddl_blocker_exception_off(THD *thd); Helper Methods -------------- Aside from the methods listed above, the following helper methods shall be implemented in the service interface. Their function is shown above each. /* Check to see if db_name is an internal database such as mysql of information_schema. */ bool is_internal_db_name(const String *db_name); /* Check if the given directory actually exists. */ bool check_db_existence(const String *db_name);
Copyright (c) 2000, 2024, Oracle Corporation and/or its affiliates. All rights reserved.