MySQL插件调用

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:

简单记录以备学习,如果有误请指出。


一、核心类

  • Observer_info:观察者 rpl_handler.h
class Observer_info {  //插件观察者
public:
  void *observer; //这个void指针是具体的观察者,使用指针函数实现多态
  st_plugin_int *plugin_int;
  plugin_ref plugin
  Observer_info(void *ob, st_plugin_int *p);
};
  • 实际观察者
    及void* 指向的对象,其中全部都是函数指针,这里通过函数指针指向了具体的函数,实现了插件的功能。其中的函数指针指向的实际函数就是需要用户自己实现的。
Trans_observer 结构体
Server_state_observer 结构体
Binlog_transmit_observer 结构体
Binlog_relay_IO_observer 结构体

实际上看具体实现的时候,搜索这些结构的名字,插件中如果实现会定义实际的函数名。如MGR中如下:

Trans_observer trans_observer = {
  sizeof(Trans_observer),

  group_replication_trans_before_dml,
  group_replication_trans_before_commit,
  group_replication_trans_before_rollback,
  group_replication_trans_after_commit,
  group_replication_trans_after_rollback,
};
  • Delegate:委托者基类
    其中包含
  Observer_info_list observer_info_list; //观察者链表,也就是Observer_info的一个链表
  mysql_rwlock_t lock;//读写锁
  MEM_ROOT memroot;//内存空间
  bool inited;//是否初始化

并且实现了一些通用的函数,比如增加和删除插件

  • 具体的委托者继承自Delegate
Trans_delegate :事物相关 typedef Trans_observer Observer; 
Server_state_delegate :服务器相关 typedef Server_state_observer Observer;
Binlog_transmit_delegate  :传输相关 typedef Binlog_transmit_observer Observer;
Binlog_relay_IO_delegate  :slave 相关typedef Binlog_relay_IO_observer Observer;

二、注册函数

举例rpl_handler.cc中

int register_trans_observer(Trans_observer *observer, void *p)
{
  return transaction_delegate->add_observer(observer, (st_plugin_int *)p);
}

observer已经初始化完成,注册即可。这里加入到了观察者队列。一旦加入这个链表则,在实际使用的时候就会遍历整个链表执行相应的函数。

三、重要的宏

  • RUN_HOOK 宏
    定义如下:
#define RUN_HOOK(group, hook, args)             \
  (group ##_delegate->is_empty() ?              \
   0 : group ##_delegate->hook args)

#define NO_HOOK(group) (group ##_delegate->is_empty())

这个宏会在MySQL中代码的相应合适的位置进行调用,进入插件定义的逻辑。

  • FOREACH_OBSERVER 宏
    定义如下:
#define FOREACH_OBSERVER(r, f, thd, args)                               \
  /*
     Use a struct to make sure that they are allocated adjacent, check
     delete_dynamic().
  */                                                                    \
  Prealloced_array<plugin_ref, 8> plugins(PSI_NOT_INSTRUMENTED);        \ //定义一个插件数组
  read_lock();                                                          \
  Observer_info_iterator iter= observer_info_iter();                    \ //迭代器
  Observer_info *info= iter++;                                          \ //
  for (; info; info= iter++)                                            \
  {                                                                     \
    plugin_ref plugin=                                                  \
      my_plugin_lock(0, &info->plugin);                                 \
    if (!plugin)                                                        \
    {                                                                   \
      /* plugin is not intialized or deleted, this is not an error */   \
      r= 0;                                                             \
      break;                                                            \
    }                                                                   \
    plugins.push_back(plugin);                                          \
    if (((Observer *)info->observer)->f                                 \
        && ((Observer *)info->observer)->f args)                        \
    {                                                                   \
      r= 1;                                                             \
      sql_print_error("Run function '" #f "' in plugin '%s' failed",    \
                      info->plugin_int->name.str);                      \
      break;                                                            \
    }                                                                   \
  }                                                                     \

实际上可以看到是在遍历相应的实际委托者的链表observer_info_list,执行相应的回表函数。

四、一个实际的列子

RUN_HOOK(transaction,
                 before_commit,
                 (thd, all,
                  thd_get_cache_mngr(thd)->get_binlog_cache_log(true),
                  thd_get_cache_mngr(thd)->get_binlog_cache_log(false),
                  max<my_off_t>(max_binlog_cache_size,
                                max_binlog_stmt_cache_size))

根据RUN_HOOK定义 group ##_delegate->hook args 转换为:

transaction_delegate->before_commit(thd, all,
                  thd_get_cache_mngr(thd)->get_binlog_cache_log(true),
                  thd_get_cache_mngr(thd)->get_binlog_cache_log(false),
                  max<my_off_t>(max_binlog_cache_size,
                                max_binlog_stmt_cache_size)

此处的transaction_delegate是一个已经初始化的并且已经有插件注册的Trans_delegate类的全局对象。因为Trans_delegate继承来自Delegate,而在Trans_delegate中实现了before_commit的逻辑。其中包含的宏调用

FOREACH_OBSERVER(ret, before_commit, thd, (&param)); //这里会执行回调函数
宏定义:(#define FOREACH_OBSERVER(r, f, thd, args)  )

做回调,实际上他会遍历整个transaction_delegate中的观察者,这些观察者就是每一个插件实现的特定的GROUP的功能,所以FOREACH_OBSERVER宏的这一句

((Observer *)info->observer)->f args

就装换为了(Trans_observer *)info->observer)->before_commit(&param) 其中info是一个Observer_info对象其中包含了一个VOID指针observer,可以转换为需要的类型,而Trans_observer是一个结构体其中全部都是函数指针before_commit是一个函数指针指向了group_replication_trans_before_commit,整个回调过程完成。

五、一张调用图

调用图如下:
RUN_HOOK.png

作者微信:
微信.jpg

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
7月前
|
SQL 存储 自然语言处理
玩转阿里云RDS PostgreSQL数据库通过pg_jieba插件进行分词
在当今社交媒体的时代,人们通过各种平台分享自己的生活、观点和情感。然而,对于平台管理员和品牌经营者来说,了解用户的情感和意见变得至关重要。为了帮助他们更好地了解用户的情感倾向,我们可以使用PostgreSQL中的pg_jieba插件对这些发帖进行分词和情感分析,来构建一个社交媒体情感分析系统,系统将根据用户的发帖内容,自动判断其情感倾向是积极、消极还是中性,并将结果存储在数据库中。
玩转阿里云RDS PostgreSQL数据库通过pg_jieba插件进行分词
|
8月前
|
SQL 存储 JSON
Blueprints MySQL Connector / UE4 | DTMysql插件使用说明
Blueprints MySQL Connector / UE4 | DTMysql插件使用说明
217 0
|
10月前
|
安全 关系型数据库 MySQL
从输入任何密码都可以直接登录 MySQL 的 root 用户谈 auth_socket 验证插件---发表到爱可生开源社区
一线的工程师反映了一个奇怪的现象,刚刚从 MySQL 官网上下载了一个 MySQL 5.7.31,安装完成后,发现使用任何密码都能登陆 MySQL,修改密码也不管用,重新启动 MySQL 也不能解决。
303 0
|
10月前
|
Oracle 关系型数据库 MySQL
迁移MariaDB审计插件(Audit Plugin)到MySQL 5.7---发表到爱可生开源社区
Oracle的MySQL社区版本不带审计插件(Audit Plugin),要想使用审计功能,你可以用Enterprise的版本,不过这需要银子。业界还有一些GPL协议的审计插件,这里我们选择MariaDB的审计插件。
123 0
|
10月前
|
关系型数据库 MySQL
MySQL 8 默认身份验证插件caching_sha2_password
默认身份验证插件caching_sha2_password
159 0
|
10月前
|
存储 SQL 监控
在MySQL社区版中也用上审计插件
在MySQL社区版中也用上审计插件
462 0
|
12月前
|
存储 关系型数据库 MySQL
为什么MySQL采用了插件式的存储引擎架构?底层原理是什么?
为什么MySQL采用了插件式的存储引擎架构?底层原理是什么?
147 0
|
12月前
|
存储 关系型数据库 MySQL
MySQL的插件式的存储引擎架构是什么意思?底层原理是什么?
MySQL的插件式的存储引擎架构是什么意思?底层原理是什么?
203 0
|
SQL 存储 缓存
MySQL查询重写插件
MySQL查询重写插件
143 0
MySQL查询重写插件
|
数据可视化 关系型数据库 MySQL
一篇永久摆脱Mysql时区错误问题,idea数据库可视化插件配置
一篇永久摆脱Mysql时区错误问题,idea数据库可视化插件配置
一篇永久摆脱Mysql时区错误问题,idea数据库可视化插件配置