我的编程空间,编程开发者的网络收藏夹
学习永远不晚

MySQL中如何编写daemon plugin

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

MySQL中如何编写daemon plugin

这篇文章给大家介绍MySQL中如何编写daemon plugin,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

1.什么是DaemonPlugin

顾名思义,daemon plugin就是一种用来在后台运行的插件,在插件中,我们可以创建一些后台线程来做些有趣的事情。大名鼎鼎的handlesocket就是一个daemon plugin。而在mysql5.6中,也是通过daemon plugin来实现了memcached功能。

2.为什么使用DaemonPlugin

就像handlersocket,大胆的想象力能够创造无限的可能。MySQL Plugin的诱人之处在于其与Mysqld处于同一进程空间中,可以利用任何mysql内核的函数。Handlersocket在实现时,构造出相关参数并直接调用存储引擎的接口,从而穿越了语法解析和优化部分,对于逻辑简单的查询而言,可以极大的提高效率。

另外所有的plugin都提供了showstatus和show variables 命令的接口,因此我们可以利用plugin来显示一些我们想要的信息,例如mysql内部的全局变量值。

总的来说,daemon plugin可以做到以下几点:

1) 创建后台线程,扩展mysql功能

2)扩展status和variables信息

Deamon plugin在mysqld启动时进行初始化,执行完init函数, 因此并不适用于与服务器进行通信的情形,mysql也没有提供任何相关的API

3.如何编写daemonplugin

这里涉及到的一些结构体,对其他类型的plugin而言也是通用的

1)st_mysql_plugin

无论声明哪种plugin,至少要包含该结构体

在plugin.h里提供了宏,我们可以通过宏来声明插件:

mysql_declare_plugin(my_plugin)

{},

{},

……

mysql_declare_plugin_end;

在两个宏之间,我们可以声明多个插件,也就是说在一个文件里,我们可以定义多个Plugin。

上面提到三个结构体,需要在plugin里单独进行定义:

a. st_mysql_daemon

该结构体只包含一个字段,用于声明daemon plugin的版本信息

也许有同学注意到了,这上面提到了两个version,即st_mysql_plugin里的version和st_mysql_daemon里的version,这两者是不相同的。

st_mysql_plugin.version记录的是该plugin的版本号,使用16进制表示,低8位存储副版本号,其他存储主版本号。

而st_mysql_daemon里存储的是daemonplugin接口的版本号,针对不同的mysql版本,其接口可能会发生变化。

b. st_mysql_show_var

结构体如下:

该结构体用于定义show status时显示的值,可以看出在type字段最后两个相对其他比较特殊。

当type类型为SHOW_ARRAY时,表明name字段并不是一个值,而是指向一个st__show_var类型的数组,数组以{0,0,0}结束,当前元素的name会成为引用数组元素name的前缀。

当type类型为SHOW_FUNC时,value值为一个函数指针,参数包括当前线程的THD,st_mysql_show_var* 以及一个大小为1024字节的内存区域头指针;函数的目的是为了填充第二个字段的值,而buf作为存储构建结构体的内存空间;这样可以允许我们先做一些计算,然后显示计算的结果。

c. st_mysql_sys_var

该结构体内包含一个宏MYSQL_PLUGIN_VAR_HEADER,包含了变量结构体的公共部分。

在这里,MySQL巧妙的使用了C的宏定义,例如,当我们定义一个variable:

struct st_mysql_sys_var* my_sysvars[]= {

MYSQL_SYSVAR(my_var),

NULL}

展开MYSQL_SYSVAR看看:

#define MYSQL_SYSVAR_NAME(name)mysql_sysvar_ ## name

#define MYSQL_SYSVAR(name) \

 ((struct st_mysql_sys_var *)&(MYSQL_SYSVAR_NAME(name)))

那么MYSQL_SYSVAR(my_var)被转换为:

((struct st_mysql_sys_var *)mysql_sysvar_my_var

因此,在这之前,我们首先要先创建好结构体。针对不同的数据类型,提供了许多宏来创建,分为两种:一种以MYSQL_SYSVAR开头的全局变量(可以set global),另外一种是MYSQL_THDVAR开头的session变量

宏中参数描述如下:

在check函数里,我们从var中提取出新的值,并存储到save指针中。在update函数中,我们可以从save指针提取出新值,st_mysql_value正是用于提取新值的结构体,成员为函数指针,如下:

例如:

Int a ;

Var->val_int(var, &a);

一些系统变量允许为SET或者ENUM类型,这时候,需要通过额外的结构体st_typelib来定义:

举个简单的例子,比如我们想定义一个INT变量,该变量为只读类型,即不允许通过set命令修改,最大为1000000,最小为0 ,默认值为 256:

Static int xx

Static MYSQL_SYSVAR_INT(xx_var, xx , PLUGIN_VAR_READONLY , “a read onlyint var”, NULL, NULL,256, 0, 1000000, 10)

例如,如果plugin的名字为name,则变量的全名为name_xx_var。我们可以将系统变量通过命令行来赋值,也可以写在配置文件中,变量名为name-xx-var,赋值必须能被10整除,否则将被mysql拒绝。

定义一个枚举类型,session变量

static const char *mode_names[] = {

"NORMAL", "TURBO","SUPER", "HYPER", "MEGA"

};

static TYPELIB modes = { 5, NULL,mode_names, NULL };

static MYSQL_THDVAR_ENUM(mode,PLUGIN_VAR_NOCMDOPT,

"one of NORMAL, TURBO, SUPER, HYPER,MEGA",

NULL, NULL, 0, &modes);

该变量属于枚举类型,每个session拥有自己的值,并且可在运行时修改;注意,当为session变量时,我们需要通过THDVAR(thd,mode)这样一个宏来获取相应的变量值

另外,对于Plugin中的系统变量无需加互斥锁,MySQL会自动给我们加上。

实例:启动一个后台线程,每隔5秒监控当前进程的状态(记录到log中),使用系统变量来控制是否记录log,并在show status显示记录的次数

#include <string.h> 

#include <plugin.h> 

#include<mysql_version.h> 

#include <my_global.h> 

#include <my_sys.h> 

#include<sys/resource.h> 

#include <sys/time.h> 

#define MONITORING_BUFFER1024 

 

extern ulong thread_id;  //当前最大线程id 

extern uint thread_count;  //当前线程数 

extern ulong max_connections;//最大允许连接数 

static pthread_tmonitoring_thread; //线程id 

static int monitoring_file;         //日志文件fd 

static my_bool monitor_state= 1;   //为1表示记录日志,为0则否 

static ulong monitor_num     = 0;   //后台线程循环次数 

static struct rusage usage;         

 

MYSQL_SYSVAR_BOOL(monitors_state,monitor_state, 

              PLUGIN_VAR_OPCMDARG, 

              "disable monitor  if 0,default TRUE", 

              NULL, NULL, TRUE); 

struct st_mysql_sys_var*vars_system_var[] = { 

        MYSQL_SYSVAR(monitors_state), 

            NULL 

}; 

 

static structst_mysql_show_var sys_status_var[] = 

    {"monitor_num", (char *)&monitor_num, SHOW_LONG}, 

    {0, 0, 0} 

}; 

 

pthread_handler_tmonitoring(void *p) 

    char buffer[MONITORING_BUFFER]; 

    char time_str[20]; 

while(1) { 

 

        sleep(5); 

        if (!monitor_state) 

            continue; 

        monitor_num++; 

 

        get_date(time_str, GETDATE_DATE_TIME,0); 

        snprintf(buffer, MONITORING_BUFFER,"%s: %u of %lu clients connected, " 

                "%lu connections made\n", 

                time_str, thread_count, 

                max_connections, thread_id); 

 

        if (getrusage(RUSAGE_SELF, &usage)== 0){ 

            snprintf(buffer+strlen(buffer) , 

MONITORING_BUFFER, "user time:%d,system time:%d," 

                                                "maxrss:%d,ixrss:%d,idrss:%d," 

                                                "isrss:%d, minflt:%d, majflt:%d," 

                                                 "nswap:%d,inblock:%d,oublock:%d," 

                                                "msgsnd:%d, msgrcv:%d,nsignals:%d," 

                                                "nvcsw:%d, nivcsw:%d\n", 

                       usage.ru_utime, 

                       usage.ru_stime, 

                       usage.ru_maxrss, 

                       usage.ru_ixrss, 

                       usage.ru_idrss, 

                       usage.ru_isrss, 

                       usage.ru_minflt, 

                       usage.ru_majflt, 

                       usage.ru_nswap, 

                       usage.ru_inblock, 

                       usage.ru_oublock, 

                       usage.ru_msgsnd, 

                       usage.ru_msgrcv, 

                       usage.ru_nsignals, 

                       usage.ru_nvcsw, 

                       usage.ru_nivcsw); 

             

            write(monitoring_file, buffer,strlen(buffer)); 

        } 

    } 

 

static int monitoring_plugin_init(void*p) 

    pthread_attr_t attr; 

    char monitoring_filename[FN_REFLEN]; 

    char buffer[MONITORING_BUFFER]; 

    char time_str[20]; 

     monitor_num = 0; 

     

    fn_format(monitoring_filename,"monitor", "", ".log", 

            MY_REPLACE_EXT |MY_UNPACK_FILENAME); 

    unlink(monitoring_filename); 

    monitoring_file = open(monitoring_filename, 

            O_CREAT | O_RDWR, 0644); 

    if (monitoring_file < 0) 

    { 

        fprintf(stderr, "Plugin'monitoring': " 

                "Could not create file '%s'\n", 

                monitoring_filename); 

        return 1; 

    } 

    get_date(time_str, GETDATE_DATE_TIME, 0); 

    sprintf(buffer, "Monitoring started at%s\n", time_str); 

    write(monitoring_file, buffer,strlen(buffer)); 

    pthread_attr_init(&attr); 

    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE); 

    if (pthread_create(&monitoring_thread,&attr, 

                monitoring, NULL) != 0){ 

        fprintf(stderr, "Plugin'monitoring': " 

                "Could not create monitoringthread!\n"); 

        return 1; 

    } 

    return 0; 

 

static intmonitoring_plugin_deinit(void *p) 

    char buffer[MONITORING_BUFFER]; 

char time_str[20]; 

 

    pthread_cancel(monitoring_thread); 

    pthread_join(monitoring_thread, NULL); 

    get_date(time_str, GETDATE_DATE_TIME, 0); 

    sprintf(buffer, "Monitoring stopped at%s\n", time_str); 

    write(monitoring_file, buffer,strlen(buffer)); 

    close(monitoring_file); 

    return 0; 

struct st_mysql_daemonmonitoring_plugin = { MYSQL_DAEMON_INTERFACE_VERSION }; 

 

mysql_declare_plugin(monitoring) 

    MYSQL_DAEMON_PLUGIN, 

    &monitoring_plugin, 

    "monitoring", 

    "yinfeng", 

    "a daemon montor,log process usagestate", 

    PLUGIN_LICENSE_GPL, 

    monitoring_plugin_init, 

    monitoring_plugin_deinit, 

    0x0100, 

    sys_status_var, 

    vars_system_var, 

    NULL 

mysql_declare_plugin_end; 

关于MySQL中如何编写daemon plugin就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

MySQL中如何编写daemon plugin

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

java中runtime.exec()如何编写

这篇文章主要介绍java中runtime.exec()如何编写,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!那就首先说点Runtime类吧,他是一个与JVM运行时环境有关的类,这个类是Singleton的。我说几个自
2023-06-03

如何在MySQL中使用PHP编写触发器

如何在MySQL中使用PHP编写触发器MySQL是一种常用的关系型数据库管理系统,而PHP是一种流行的服务器端脚本语言。在MySQL中使用PHP编写触发器可以帮助我们实现自动化的数据库操作。本文将介绍如何使用PHP来编写MySQL触发器,并
2023-10-22

如何在MySQL中使用JavaScript编写触发器

如何使用JavaScript编写MySQL触发器MySQL允许使用JavaScript编写触发器,从而提高灵活性并实现复杂逻辑。通过创建一个事件并编写JavaScript代码,触发器可以在数据操作时自动执行。触发器可以访问行数据、修改数据并抛出错误。尽管存在限制(例如无法访问其他表),但JavaScript触发器具有灵活性、易开发性和与其他应用程序集成的优点。在编写和维护触发器时,应注意最佳实践,包括简洁高效的代码、适当的错误处理和定期监视。
如何在MySQL中使用JavaScript编写触发器
2024-04-10

如何在MySQL中使用JavaScript编写触发器

在MySQL中使用JavaScript编写触发器并不支持,MySQL的触发器是使用SQL语言编写的。以下是创建触发器的基本语法:```mysqlCREATE TRIGGER trigger_name{BEFORE | AFTER} {INS
2023-10-10

如何在MySQL中使用Python编写存储过程

标题:MySQL中使用Python编写存储过程的示例及实践指南在MySQL中使用存储过程可以有效地将复杂的数据库操作封装起来,提高数据库的执行效率和安全性。本文将介绍如何使用Python编写MySQL的存储过程,并提供具体的代码示例供参考。
2023-10-22

如何在MySQL中使用C#编写存储过程

如何在MySQL中使用C#编写存储过程在MySQL数据库中,存储过程是一组预定义的SQL语句,可以以一定的逻辑顺序组合成一个单元的程序。它可以用于简化和优化数据库操作,并提高应用程序的性能和安全性。C#是一种广泛使用的编程语言,具有强大的数
2023-10-22

如何编写shell

这篇文章主要介绍了如何编写shell,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。引语:我本人以前并没有写过shell脚本,也许是因为懒,也许是没有被逼到要去写shell的地
2023-06-09

如何在MySQL中使用C#编写自定义函数

在MySQL中使用C#编写自定义函数需要以下步骤:1. 创建一个C#类库项目,并添加对MySQL.Data.dll的引用。2. 在C#类库项目中创建一个类,用于实现自定义函数的逻辑。例如,创建一个名为"CustomFunctions"的类。
2023-10-20

如何编写html

HTML(Hypertext Markup Language)是一种用于构建网页的标记语言,它是构建网页的基础。在本文中,我们将介绍如何编写HTML以及如何为网站添加样式和功能。1. 编写HTML文档HTML文档是由标签组成的,并且标签可以嵌套。每个标签都有一个开标签和一个闭合标签,例如:```html 这是网页标题<
2023-05-21

如何在MySQL中使用JavaScript编写自定义函数

如何在MySQL中使用JavaScript编写自定义函数MySQL是一个流行的关系型数据库管理系统,而JavaScript是一种广泛用于网页开发的脚本语言。尽管MySQL自带了许多内建函数,但有时我们可能需要编写自定义函数来满足特定的需求。
2023-10-22

如何编写bytes2BSTR

这篇文章主要介绍“如何编写bytes2BSTR”,在日常操作中,相信很多人在如何编写bytes2BSTR问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何编写bytes2BSTR”的疑惑有所帮助!接下来,请跟
2023-06-08

如何在MySQL中使用Python编写自定义函数

如何使用Python编写MySQL自定义函数在MySQL中使用Python编写自定义函数,可以扩展数据库功能,增强灵活性、代码可重用性和性能。本文提供了一个逐步指南,包括安装先决条件、创建函数、编写Python函数、调用函数和处理错误的步骤。遵循最佳实践,例如函数命名约定、类型提示和单元测试,以创建高效且可维护的自定义函数。
如何在MySQL中使用Python编写自定义函数
2024-04-10

如何在MySQL中使用Python编写自定义函数

在MySQL中使用Python编写自定义函数可以通过以下步骤实现:1. 首先,需要安装MySQL的Python驱动程序。可以使用以下命令进行安装:```pip install mysql-connector-python```2. 连接到M
2023-10-10

编程热搜

目录