扩展 MySQL 8.0  / 第 4 章 MySQL 插件 API  / 4.4 编写插件  / 4.4.2 插件数据结构  /  4.4.2.1 服务器插件库和插件描述符

4.4.2.1 服务器插件库和插件描述符

每个包含服务器插件的插件库都必须包含一个库描述符,其中包含文件中每个服务器插件的通用插件描述符。本节讨论如何编写服务器插件的库和通用描述符。

库描述符必须定义两个符号:

  • _mysql_plugin_interface_version_ 指定通用插件框架的版本号。这是由 文件MYSQL_PLUGIN_INTERFACE_VERSION 中定义的符号 给出的plugin.h

  • _mysql_plugin_declarations_定义一个插件声明数组,以所有成员都设置为 0 的声明终止。每个声明都是st_mysql_plugin 结构的一个实例(也在 中定义 plugin.h)。库中的每个服务器插件都必须有其中之一。

如果服务器在一个库中没有找到这两个符号,它就不会接受它作为一个合法的插件库,并以错误的方式拒绝它。这可以防止将库用于插件目的,除非它是专门作为插件库构建的。

定义两个必需符号的常规方法是使用文件中的mysql_declare_plugin()mysql_declare_plugin_endplugin.h

mysql_declare_plugin(name)
 ... one or more server plugin descriptors here ...
mysql_declare_plugin_end;

每个服务器插件都必须有一个通用描述符,用于向服务器插件 API 提供信息。通用描述符对所有插件类型具有相同的结构。文件中的 st_mysql_plugin结构 plugin.h定义了这个描述符:

struct st_mysql_plugin
{
  int type;             /* the plugin type (a MYSQL_XXX_PLUGIN value)   */
  void *info;           /* pointer to type-specific plugin descriptor   */
  const char *name;     /* plugin name                                  */
  const char *author;   /* plugin author (for I_S.PLUGINS)              */
  const char *descr;    /* general descriptive text (for I_S.PLUGINS)   */
  int license;          /* the plugin license (PLUGIN_LICENSE_XXX)      */
  int (*init)(void *);  /* the function to invoke when plugin is loaded */
  int (*deinit)(void *);/* the function to invoke when plugin is unloaded */
  unsigned int version; /* plugin version (for I_S.PLUGINS)             */
  struct st_mysql_show_var *status_vars;
  struct st_mysql_sys_var **system_vars;
  void * __reserved1;   /* reserved for dependency checking             */
  unsigned long flags;  /* flags for plugin */
};

描述st_mysql_plugin符结构成员使用如下。char * 成员应指定为以 null 结尾的字符串。

  • type: 插件类型。这必须是以下插件类型值之一 plugin.h

    /*
      The allowable types of plugins
    */
    #define MYSQL_UDF_PLUGIN 0                /* User-defined function        */
    #define MYSQL_STORAGE_ENGINE_PLUGIN 1     /* Storage Engine               */
    #define MYSQL_FTPARSER_PLUGIN 2           /* Full-text parser plugin      */
    #define MYSQL_DAEMON_PLUGIN 3             /* The daemon/raw plugin type */
    #define MYSQL_INFORMATION_SCHEMA_PLUGIN 4 /* The I_S plugin type */
    #define MYSQL_AUDIT_PLUGIN 5              /* The Audit plugin type        */
    #define MYSQL_REPLICATION_PLUGIN 6        /* The replication plugin type */
    #define MYSQL_AUTHENTICATION_PLUGIN 7     /* The authentication plugin type */
    #define MYSQL_VALIDATE_PASSWORD_PLUGIN 8  /* validate password plugin type */
    #define MYSQL_GROUP_REPLICATION_PLUGIN 9  /* The Group Replication plugin */
    #define MYSQL_KEYRING_PLUGIN 10           /* The Keyring plugin type   */
    #define MYSQL_CLONE_PLUGIN 11             /* The Clone plugin type   */

    例如,对于全文解析器插件,该 type值为 MYSQL_FTPARSER_PLUGIN.

  • info:指向插件的特定类型描述符的指针。此描述符的结构取决于特定类型的插件,与一般插件描述符结构不同。出于版本控制的目的,每个插件类型的特定于类型的描述符的第一个成员应该是该类型的接口版本。这使服务器能够检查每个插件的特定类型版本,无论其类型如何。在版本号之后,描述符包括所需的任何其他成员,例如回调函数和服务器正确调用插件所需的其他信息。

  • name:给出插件名称的字符串。这是将在 mysql.plugin表中列出的名称,您可以通过它在 SQL 语句中引用插件,例如 INSTALL PLUGINand UNINSTALL PLUGIN,或带有--plugin-load选项。INFORMATION_SCHEMA.PLUGINS 该名称在表或 的输出中也可见 SHOW PLUGINS

    插件名称不应以任何服务器选项的名称开头。如果是这样,服务器将无法初始化它。例如,服务器有一个 选项 --socket,因此您不应使用 、 等插件名称 。 socketsocket_plugin

  • author:命名插件作者的字符串。这可以是任何你喜欢的。

  • desc:提供插件一般描述的字符串。这可以是任何你喜欢的。

  • license:插件许可证类型。该值可以是 PLUGIN_LICENSE_PROPRIETARYPLUGIN_LICENSE_GPL或 之一PLUGIN_LICENSE_BSD

  • init: 一个一次性的初始化函数,或者NULL如果没有这样的函数。服务器在加载插件时执行此函数,这发生 在服务器启动时INSTALL PLUGIN或对于表中列出的插件。mysql.plugin该函数采用一个参数,该参数指向用于识别插件的内部结构。成功返回零,失败返回非零。

  • deinit: 一个一次性的反初始化函数,或者NULL如果没有这样的函数。服务器在卸载插件时执行此函数,这发生 在服务器关闭时UNINSTALL PLUGIN或对于表中列出的插件。mysql.plugin该函数采用一个指向用于识别插件的内部结构的参数。它返回零表示成功,非零表示失败。

  • version: 插件版本号。安装插件后,可以从 INFORMATION_SCHEMA.PLUGINS 表中检索该值。该值包括主要和次要数字。如果将值写为十六进制常量,则格式为 ,其中和 分别是主要和次要数字。例如, 表示版本 3.2。 0xMMNNMMNN0x0302

  • status_vars:指向与插件关联的状态变量结构的指针,或者 NULL如果没有这样的变量。安装插件后,这些变量会显示在SHOW STATUS语句的输出中。

    status_vars成员(如果不是 NULL)指向 st_mysql_show_var描述状态变量的结构数组。请参阅 第 4.4.2.2 节,“服务器插件状态和系统变量”

  • system_vars:指向与插件关联的系统变量结构的指针,或者 NULL如果没有这样的变量。这些选项和系统变量可用于帮助初始化插件中的变量。安装插件后,这些变量会显示在SHOW VARIABLES语句的输出中。

    system_vars成员(如果不是 NULL)指向 st_mysql_sys_var描述系统变量的结构数组。请参阅 第 4.4.2.2 节,“服务器插件状态和系统变量”

  • __reserved1: 未来的占位符。它应该设置为NULL

  • flags:插件标志。各个位对应于不同的标志。该值应设置为适用标志的 OR。这些标志可用:

    #define PLUGIN_OPT_NO_INSTALL   1UL   /* Not dynamically loadable */
    #define PLUGIN_OPT_NO_UNINSTALL 2UL   /* Not dynamically unloadable */
    #define PLUGIN_OPT_ALLOW_EARLY  4UL   /* allow --early-plugin-load */

    启用时,这些标志具有以下含义:

    • PLUGIN_OPT_NO_INSTALL: 无法在运行时使用该 INSTALL PLUGIN 语句加载插件。这适用于必须在服务器启动时使用 、 或 选项加载 --plugin-load--plugin-load-add插件 --early-plugin-load

    • PLUGIN_OPT_NO_UNINSTALL: 插件不能在运行时用 UNINSTALL PLUGIN 语句卸载。

    • PLUGIN_OPT_ALLOW_EARLY:可以使用 --early-plugin-load 选项在服务器启动序列的早期加载插件。--plugin-load此标志对是否可以在服务器启动时使用或 --plugin-load-add 选项或在运行时使用 INSTALL PLUGIN 语句 加载插件没有影响 。

      这个标志是在 MySQL 8.0.17 中添加的。使用 8.0.17 之前的 MySQL 发行版编译的所有插件都没有设置此标志。将这些加载到 8.0.17 之前的服务器时这无关紧要,但是尝试将使用 --early-plugin-load 8.0.17 之前的 MySQL 发行版编译的插件二进制文件加载到 8.0.17 或更高版本的服务器中将会失败。必须针对 MySQL 8.0.17 或更高版本重新编译插件。

服务器仅在加载和卸载插件时调用通用插件描述符中的init和 函数。deinit它们与插件的使用无关,例如当 SQL 语句导致调用插件时发生的情况。

例如,包含名为的单个全文解析器插件的库的描述符信息 simple_parser如下所示:

mysql_declare_plugin(ftexample)
{
  MYSQL_FTPARSER_PLUGIN,      /* type                            */
  &simple_parser_descriptor,  /* descriptor                      */
  "simple_parser",            /* name                            */
  "Oracle Corporation",       /* author                          */
  "Simple Full-Text Parser",  /* description                     */
  PLUGIN_LICENSE_GPL,         /* plugin license                  */
  simple_parser_plugin_init,  /* init function (when loaded)     */
  simple_parser_plugin_deinit,/* deinit function (when unloaded) */
  0x0001,                     /* version                         */
  simple_status,              /* status variables                */
  simple_system_variables,    /* system variables                */
  NULL,
  0
}
mysql_declare_plugin_end;

对于全文解析器插件,类型必须是 MYSQL_FTPARSER_PLUGIN. 这是在 WITH PARSER创建 FULLTEXT索引时将插件标识为在子句中合法使用的值。(对于此条款,其他插件类型均不合法。)

plugin.h像这样定义 mysql_declare_plugin()mysql_declare_plugin_end宏:

#ifndef MYSQL_DYNAMIC_PLUGIN
#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS) \
MYSQL_PLUGIN_EXPORT int VERSION= MYSQL_PLUGIN_INTERFACE_VERSION; \
MYSQL_PLUGIN_EXPORT int PSIZE= sizeof(struct st_mysql_plugin); \
MYSQL_PLUGIN_EXPORT struct st_mysql_plugin DECLS[]= {
#else
#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS) \
MYSQL_PLUGIN_EXPORT int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \
MYSQL_PLUGIN_EXPORT int _mysql_sizeof_struct_st_plugin_= sizeof(struct st_mysql_plugin); \
MYSQL_PLUGIN_EXPORT struct st_mysql_plugin _mysql_plugin_declarations_[]= {
#endif

#define mysql_declare_plugin(NAME) \
__MYSQL_DECLARE_PLUGIN(NAME, \
                 builtin_ ## NAME ## _plugin_interface_version, \
                 builtin_ ## NAME ## _sizeof_struct_st_plugin, \
                 builtin_ ## NAME ## _plugin)

#define mysql_declare_plugin_end ,{0,0,0,0,0,0,0,0,0,0,0,0,0}}
笔记

这些声明 _mysql_plugin_interface_version_仅在MYSQL_DYNAMIC_PLUGIN符号已定义时才定义符号。这意味着 -DMYSQL_DYNAMIC_PLUGIN必须作为编译命令的一部分提供,以将插件构建为共享库。

当宏按刚才所示的方式使用时,它们会扩展为以下代码,其中定义了两个必需的符号 (_mysql_plugin_interface_version__mysql_plugin_declarations_):

int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION;
int _mysql_sizeof_struct_st_plugin_= sizeof(struct st_mysql_plugin);
struct st_mysql_plugin _mysql_plugin_declarations_[]= {
{
  MYSQL_FTPARSER_PLUGIN,      /* type                            */
  &simple_parser_descriptor,  /* descriptor                      */
  "simple_parser",            /* name                            */
  "Oracle Corporation",       /* author                          */
  "Simple Full-Text Parser",  /* description                     */
  PLUGIN_LICENSE_GPL,         /* plugin license                  */
  simple_parser_plugin_init,  /* init function (when loaded)     */
  simple_parser_plugin_deinit,/* deinit function (when unloaded) */
  0x0001,                     /* version                         */
  simple_status,              /* status variables                */
  simple_system_variables,    /* system variables                */
  NULL,
  0
}
  ,{0,0,0,0,0,0,0,0,0,0,0,0}}
};

前面的示例在通用描述符中声明了一个插件,但也可以声明多个插件。依次列出 和 之间的声明 mysql_declare_plugin()mysql_declare_plugin_end以逗号分隔。

MySQL 服务器插件必须编译为 C++ 代码。不应使用的一个 C++ 功能是用于初始化全局结构的非常量变量。结构的成员,如st_mysql_plugin结构,应该只用常量变量初始化。前面显示的 simple_parser描述符在 C++ 插件中是允许的,因为它满足该要求:

mysql_declare_plugin(ftexample)
{
  MYSQL_FTPARSER_PLUGIN,      /* type                            */
  &simple_parser_descriptor,  /* descriptor                      */
  "simple_parser",            /* name                            */
  "Oracle Corporation",       /* author                          */
  "Simple Full-Text Parser",  /* description                     */
  PLUGIN_LICENSE_GPL,         /* plugin license                  */
  simple_parser_plugin_init,  /* init function (when loaded)     */
  simple_parser_plugin_deinit,/* deinit function (when unloaded) */
  0x0001,                     /* version                         */
  simple_status,              /* status variables                */
  simple_system_variables,    /* system variables                */
  NULL,
  0
}
mysql_declare_plugin_end;

这是编写通用描述符的另一种有效方法。它使用常量变量来指示插件名称、作者和描述:

const char *simple_parser_name = "simple_parser";
const char *simple_parser_author = "Oracle Corporation";
const char *simple_parser_description = "Simple Full-Text Parser";

mysql_declare_plugin(ftexample)
{
  MYSQL_FTPARSER_PLUGIN,      /* type                            */
  &simple_parser_descriptor,  /* descriptor                      */
  simple_parser_name,         /* name                            */
  simple_parser_author,       /* author                          */
  simple_parser_description,  /* description                     */
  PLUGIN_LICENSE_GPL,         /* plugin license                  */
  simple_parser_plugin_init,  /* init function (when loaded)     */
  simple_parser_plugin_deinit,/* deinit function (when unloaded) */
  0x0001,                     /* version                         */
  simple_status,              /* status variables                */
  simple_system_variables,    /* system variables                */
  NULL,
  0
}
mysql_declare_plugin_end;

但是,下面的通用描述符是无效的。它使用结构成员来指示插件名称、作者和描述,但结构在 C++ 中不被视为常量初始值设定项:

typedef struct
{
  const char *name;
  const char *author;
  const char *description;
} plugin_info;

plugin_info parser_info = {
  "simple_parser",
  "Oracle Corporation",
  "Simple Full-Text Parser"
};

mysql_declare_plugin(ftexample)
{
  MYSQL_FTPARSER_PLUGIN,      /* type                            */
  &simple_parser_descriptor,  /* descriptor                      */
  parser_info.name,           /* name                            */
  parser_info.author,         /* author                          */
  parser_info.description,    /* description                     */
  PLUGIN_LICENSE_GPL,         /* plugin license                  */
  simple_parser_plugin_init,  /* init function (when loaded)     */
  simple_parser_plugin_deinit,/* deinit function (when unloaded) */
  0x0001,                     /* version                         */
  simple_status,              /* status variables                */
  simple_system_variables,    /* system variables                */
  NULL,
  0
}
mysql_declare_plugin_end;