mysql plugin 开发_Mysql源代码分析(5): Plugin架构介绍--转载

本文介绍了MySQL插件开发中的Plugin架构,包括动态和静态链接的区别,以daemon_example插件为例展示了如何声明和定义插件。在MySQL源代码中,众多插件如partition、binlog等都使用`mysql_declare_plugin`进行声明。`plugin_init()`函数负责初始化静态链接的插件,通过调用各插件的初始化函数进行设置。
摘要由CSDN通过智能技术生成

#define mysql_declare_plugin_end ,{0,0,0,0,0,0,0,0,0,0,0,0}}

__MYSQL_DECLARE_PLUGIN根据plugin是动态链接plugin还是静态链接plugin有不同的定义:

#ifndef MYSQL_DYNAMIC_PLUGIN

#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS) \

int VERSION= MYSQL_PLUGIN_INTERFACE_VERSION; \

int PSIZE= sizeof(struct st_mysql_plugin); \

struct st_mysql_plugin DECLS[]= {

#else

#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS) \

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_[]= {

#endif

特别要注意的是“#ifndef MYSQL_DYNAMIC_PLUGIN”,如果你要写的plugin是动态加载的话,需要在编译的时候定义这个宏。

总体而 言,mysql_declare_plugin申明了一个struct st_mysql_plugin数组,开发者需要在该宏之后填写plugin自定义的st_mysql_plugin各个成员,并通过 mysql_declare_plugin_end结束这个数组。

看个例子 plugin/daemon_example/daemon_example.cc,这是个动态MYSQL_DAEMON_PLUGIN类型的 plugin,注意到plugin/daemon_example/Makefile.am里面有-DMYSQL_DYNAMIC_PLUGIN。具体定 义如下:

mysql_declare_plugin(daemon_example)

{

MYSQL_DAEMON_PLUGIN,

&daemon_example_plugin,

"daemon_example",

"Brian Aker",

"Daemon example, creates a heartbeat beat file in mysql-heartbeat.log",

PLUGIN_LICENSE_GPL,

daemon_example_plugin_init, /* Plugin Init */ // plugin初始化入口

daemon_example_plugin_deinit, /* Plugin Deinit */    // plugin清理函数

0x0100 /* 1.0 */,

NULL, /* status variables */

NULL, /* system variables */

NULL /* config options */

}

mysql_declare_plugin_end;

这个定义经过preprocess被展开后定义为:

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_DAEMON_PLUGIN,

&daemon_example_plugin,

"daemon_example",

"Brian Aker",

"Daemon example, creates a heartbeat beat file in mysql-heartbeat.log",

PLUGIN_LICENSE_GPL,

daemon_example_plugin_init, /* Plugin Init */ // plugin初始化入口

daemon_example_plugin_deinit, /* Plugin Deinit */    // plugin清理函数

0x0100 /* 1.0 */,

NULL, /* status variables */

NULL, /* system variables */

NULL /* config options */

} , {0,0,0,0,0,0,0,0,0,0,0,0}};

静态链接plugin也类似,只不过plugin宏展开出来的变量都有自己的名字,对于myisam,生成了一个叫builtin_myisam_plugin的plugin数组。

plugin可以定义自己的变量,包括系统变量和状态变量。具体的例子可以看看storage/innobase/handler/ha_innodb.cc里面对于innodb插件的申明,结合plugin.h,还是比较容易看懂的。

在mysql的源代码里面grep一把mysql_declare_plugin,看看都有哪些plugin:

$grep "mysql_declare_plugin(" --include=*.cc -rni *

plugin/daemon_example/daemon_example.cc:187:mysql_declare_plugin(daemon_example)

sql/ha_partition.cc:6269:mysql_declare_plugin(partition)

sql/log.cc:5528:mysql_declare_plugin(binlog)

sql/ha_ndbcluster.cc:10533:mysql_declare_plugin(ndbcluster)

storage/csv/ha_tina.cc:1603:mysql_declare_plugin(csv)

storage/example/ha_example.cc:893:mysql_declare_plugin(example)

storage/myisam/ha_myisam.cc:2057:mysql_declare_plugin(myisam)

storage/heap/ha_heap.cc:746:mysql_declare_plugin(heap)

storage/innobase/handler/ha_innodb.cc:8231:mysql_declare_plugin(innobase)

storage/myisammrg/ha_myisammrg.cc:1186:mysql_declare_plugin(myisammrg)

storage/blackhole/ha_blackhole.cc:356:mysql_declare_plugin(blackhole)

storage/federated/ha_federated.cc:3368:mysql_declare_plugin(federated)

storage/archive/ha_archive.cc:1627:mysql_declare_plugin(archive)

呵呵,连binlog都是plugin哦,不过还是storage plugin占大多数。

Plugin初始化

在见面的介绍main函数的文章中我也提到了其中有个函数plugin_init()是初始化的一部分,这个东东就是所有静态链接初始化plugin的初始化入口。该函数定义在"sql/sql_plugin.cc"中。

int plugin_init(int *argc, char **argv, int flags) {

// 初始化内存分配pool。

init_alloc_root(&plugin_mem_root, 4096, 4096);

init_alloc_root(&tmp_root, 4096, 4096);

// hash结构初始化

...

// 初始化运行时plugin数组,plugin_dl_array用来保存动态加载plugin,plugin_array保存静态链接plugin。而且最多各自能有16个plugin。

my_init_dynamic_array(&plugin_dl_array, sizeof(struct st_plugin_dl *),16,16);

my_init_dynamic_array(&plugin_array, sizeof(struct st_plugin_int *),16,16);

// 初始化静态链接plugin

for (builtins= mysqld_builtins; *builtins; builtins++) {

// 每一个plugin还可以有多个子plugin,参见见面的plugin申明。

for (plugin= *builtins; plugin->info; plugin++) {

register_builtin(plugin, &tmp, &plugin_ptr); // 将plugin放到plugin_array和plugin_hash中。

// 这个时候只初始化csv或者myisam plugin。

plugin_initialize(plugin_ptr); // 初始化plugin,调用plugin的初始化函数,将plugin的状态变量加入到状态变量列表中,将系统变量的plugin成员指向当前的活动plugin。

}

}

// 根据用户选项初始化动态加载plugin

if (!(flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING))

{

if (opt_plugin_load)

plugin_load_list(&tmp_root, argc, argv, opt_plugin_load); // 根据配置加载制定的plugin。包括找到dll,加载,寻找符号并设置plugin结构。

if (!(flags & PLUGIN_INIT_SKIP_PLUGIN_TABLE))

plugin_load(&tmp_root, argc, argv); // 加载系统plugin table中的plugin。

}

// 初始化剩下的plugin。

for (i= 0; i < plugin_array.elements; i++) {

plugin_ptr= *dynamic_element(&plugin_array, i, struct st_plugin_int **);

if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED)

{

if (plugin_initialize(plugin_ptr))

{

plugin_ptr->state= PLUGIN_IS_DYING;

*(reap++)= plugin_ptr;

}

}

}

...

}

这个函数执行结束以后,在plugin_array,plugin_dl_array,plugin_hash中保存了当前加载了的所有的plugin。到此plugin初始化结束。

在plugin_initialize 函数里面,调用了每个plugin自己的init函数(参见前面的内容)。特别要提到的是对于各种不同类型的plugin,初始化函数的参数也不一样,这 是通过一个全局的plugin_type_initialize间接层来实现的。这个数组对于每种类型的plugin定义了一个函数,比如对于 storage plugin对应的是ha_initialize_handlerton,对于information scheme对应的是initialize_schema_table,然后在这些函数中再调用plugin的初始化函数。暂时对于其他类型的 plugin没有定义这个中间层初始化函数,所以就直接调用了plugin的初始化函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DECLARE_MYSQL_PLUGIN宏的使用是用于在MySQL插件开发中声明一个自定义的MySQL插件。该宏在mysql_com.h头文件中定义。使用该宏需要在宏之后填写自定义插件的st_mysql_plugin结构的各个成员,并通过mysql_declare_plugin_end宏结束这个数组。\[1\]这个宏的使用可以参考plugin/daemon_example/daemon_example.cc文件中的例子,该例子是一个动态MYSQL_DAEMON_PLUGIN类型的插件,通过在Makefile.am文件中添加-DMYSQL_DYNAMIC_PLUGIN来定义。\[2\]这个宏的使用在MySQL 8.0.18版本中引入了一个新的功能,即支持Hash Join算法。如果优化器选择没有索引的情况下,会直接使用Hash Join,这个功能比MariaDB实现的要好。\[3\] #### 引用[.reference_title] - *1* *2* [Mysql源代码分析(5): Plugin架构介绍--转载](https://blog.csdn.net/weixin_36205186/article/details/113225861)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [mysql 5.7不支持declare_B站直播MySQL冲冲冲第一期文稿版](https://blog.csdn.net/weixin_39671374/article/details/111699497)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值