扩展 MySQL 9.0  /  插件的 MySQL 服务

第 5 章 插件的 MySQL 服务

MySQL 服务器插件可以访问服务器的“插件服务”。插件服务接口公开了插件可以调用的服务器功能。它补充了插件 API,并具有以下特点:

  • 服务使插件能够使用普通的函数调用访问服务器内部的代码。可加载函数也可以使用服务。

  • 服务是可移植的,可以在多个平台上工作。

  • 该接口包含一个版本控制机制,以便可以在加载时根据插件版本检查服务器支持的服务版本。版本控制可以防止服务器提供的服务版本与插件期望或需要的服务版本之间出现不兼容的情况。

  • 有关用于测试插件服务的插件的信息,请参阅 MySQL 服务器 Doxygen 文档中的“用于测试插件服务的插件”部分,该文档位于 https://dev.mysqlserver.cn/doc/index-other.html

插件服务接口与插件 API 的不同之处如下:

  • 插件 API 使插件能够被服务器使用。调用主动权在于服务器调用插件。这使得插件可以扩展服务器功能或注册以接收有关服务器处理的通知。

  • 插件服务接口使插件能够调用服务器内部的代码。调用主动权在于插件调用服务函数。这使得服务器中已实现的功能可以被许多插件使用;它们不需要单独实现这些功能。

要确定存在哪些服务以及它们提供哪些功能,请查看 MySQL 源代码发行版中的 include/mysql 目录。相关文件如下:

  • plugin.h 包含 services.h,它是包含所有可用服务特定头文件的“总括”头文件。

  • 服务特定头文件的名称格式为 service_xxx.h

每个服务特定头文件都应包含注释,为给定服务提供完整的用法文档,包括可用的服务函数、它们的调用顺序和返回值。

对于希望修改服务器以添加新服务的开发人员,请参阅 MySQL 内部结构:插件的 MySQL 服务

可用的服务包括:

  • get_sysvar_source:一种服务,使插件能够检索系统变量设置的来源。

  • locking_service:一种服务,它实现了具有三个属性的锁:锁命名空间、锁名称和锁模式。此锁定接口可以在两个级别访问:1) 在 SQL 级别,作为一组可加载函数,每个函数都映射到对服务例程的调用;2) 作为 C 语言接口,可以作为插件服务从服务器插件或可加载函数调用。有关更多信息,请参阅 锁定服务

  • my_plugin_log_service:一种服务,使插件能够报告错误并指定错误消息。服务器将消息写入其错误日志。

  • status_variable_registration。一种用于注册状态变量的服务。

  • my_thd_scheduler:一种服务,供插件选择线程调度程序。

  • mysql_keyring:一种用于密钥环存储的服务,可以在两个级别访问:1) 在 SQL 级别,作为一组可加载函数,每个函数都映射到对服务例程的调用;2) 作为 C 语言接口,可以作为插件服务从服务器插件或可加载函数调用。有关更多信息,请参阅 密钥环服务

  • mysql_password_policy:一种用于密码验证和强度检查的服务。

  • plugin_registry_service:MySQL 服务器包含一个基于组件的基础结构,用于改进服务器的可扩展性;请参阅 MySQL 组件。但是,MySQL 插件使用的是组件接口之前的接口。plugin_registry_service 使插件能够访问组件注册表及其服务。

  • security_context:一种服务,使插件能够检查或操作线程安全上下文。此服务提供设置器和获取器例程来访问服务器 Security_context 类的属性,该类包括操作系统用户和主机、已验证的用户和主机以及客户端 IP 地址等属性。

  • thd_alloc:一种内存分配服务。

  • thd_wait:一种服务,供插件在即将进入休眠或停滞状态时报告。

本节的其余部分介绍了插件如何使用作为服务提供的服务器功能。另请参阅“守护进程”示例插件的源代码,该插件使用了 my_snprintf 服务。在 MySQL 源代码发行版中,该插件位于 plugin/daemon_example 目录中。

要在插件中使用一个或多个服务,插件源文件必须包含 plugin.h 头文件才能访问与服务相关的信息:

#include <mysql/plugin.h>

这并不代表任何额外的设置成本。插件必须包含该文件,因为它包含每个插件都需要定义和结构。

要访问服务,插件可以像调用任何其他函数一样调用服务函数。

要报告服务器将写入其错误日志的错误,首先选择一个错误级别。mysql/service_my_plugin_log.h 定义了以下级别:

enum plugin_log_level
{
  MY_ERROR_LEVEL,
  MY_WARNING_LEVEL,
  MY_INFORMATION_LEVEL
};

然后调用 my_plugin_log_message()

int my_plugin_log_message(MYSQL_PLUGIN *plugin, enum plugin_log_level level,
                          const char *format, ...);

例如:

my_plugin_log_message(plugin_ptr, MY_ERROR_LEVEL, "Cannot initialize plugin");

某些“用于”插件的服务可能“由”插件提供,因此只有在加载了提供服务的插件时才可用。任何使用此类服务的 MySQL 组件都应检查该服务是否可用。

构建插件时,请在链接时使用 -lmysqlservices 标志链接 libmysqlservices 库。例如,对于 CMake,请将以下内容放在顶级的 CMakeLists.txt 文件中:

FIND_LIBRARY(MYSQLSERVICES_LIB mysqlservices
 PATHS "${MYSQL_SRCDIR}/libservices" NO_DEFAULT_PATH)

将以下内容放在包含插件源代码的目录中的 CMakeLists.txt 文件中:

# the plugin needs the mysql services library for error logging
TARGET_LINK_LIBRARIES (your_plugin_library_name ${MYSQLSERVICES_LIB})