`
whitesock
  • 浏览: 484066 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

MySQL UDF

阅读更多

    最近公司在做个SNS子项目,需要把交易系统中的交易数据实时地发送到SNS子系统中。最自然的设计是修改各个交易模块,将数据向SNS系统传输。但是在评审和开发的时候遇到了不小的阻力。理由很简单,这些修改直接影响系统的核心交易模块,引入了一定的风险。综合考虑后,决定增加个类似于Memcached Functions for MySQL的备选方案。SNS子系统虽然大量地使用了cache,但是没有使用Memcached或EHCache,原因是这些cache实现无法满足所有的需求。最初的想法是在UDF中使用ActiveMQ CPP,将消息直接发送到SNS子系统的cache中。不过最终还是放弃了这种比较激进的做法,而是在UDF中将数据通过socket发送到某个Java程序,然后再对数据进行分类处理后,转发给SNS cache。

 

    关于user-defined function(UDF),在MySQL的官方文档上有比较详细的说明。为了使用UDF,必须要动态链接mysqld,也就是不能使用--with-mysqld-ldflags=-all-static,而是应该使用--with-mysqld-ldflags=-rdynamic。UDF通常需要用C/C++编写,如果要编写一个名为xxx的UDF,那么需要定义如下的C/C++方法:

  • xxx() (required)。这个方法的返回值就是UDF的结果。SQL数据类型和C/C++类型之间的对应关系是:varchar char *;INTEGER long long;REAL double;DECIMAL char *等。
  • xxx_init() (optional)。xxx()对应的初始化方法。该方法通常用来检查xxx()方法的参数(或者进行参数类型的转换),分配内存,指定返回值的最大长度等。
  • xxx_deinit() (optional)。xxx()对应的清理方法。在这个方法中应该释放之前分配的内存。

    当在SQL中调用名为XXX()的UDF时,MySQL会首先尝试调用名为xxx_init() 的方法,如果该方法返回false,那么MySQL会终止SQL的执行,并返回一个error message(在xxx_init()中保存在message参数中的以null结尾的字符串,最大长度为 MYSQL_ERRMSG_SIZE)。否则MySQL会对每个row调用xxx() 方法。在所有的row都被处理后,MySQL会调用xxx_deinit() 方法来执行相应的清理工作。对于那些象SUM()之类的聚集函数,还有一些其他的C/C++函数需要编写。需要注意的是,如果采用C++编写UDF,由于C++的"name mangling"会导致MySQL无法找到对应的C++函数,因此需要将函数声明包含在extern "C" { ... }中。以下是这些函数的例子:

my_bool xxx_init(UDF_INIT *initid, UDF_ARGS *args, char *message);

char *xxx(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error);

void xxx_deinit(UDF_INIT *initid);

 

    initid参数会被传递到所有三个函数中(用于在这三个函数中共享数据),它指向一个UDF_INIT结构体。关于该结构体的成员,可以参考MySQL的在线文档。args参数指向一个UDF_ARGS结构体,它有如下成员:

  • unsigned int arg_count。参数的个数。
  • enum Item_result *arg_type。参数的类型。可选值有STRING_RESULT, INT_RESULT, REAL_RESULT, and DECIMAL_RESULT。DECIMAL_RESULT类型的值是以char *的形式传入到函数中的,因此处理方式同STRING_RESULT类型参数。如果xxx_init()中对该成员赋值,例如args->arg_type[0] = STRING_RESULT;那么MySQl会在调用xxx()是对 相应的参数进行强制地类型转换。
  •  char **args。参数值。如果参数值是NULL,那么args->args[i]是一个空指针(0)。对于STRING_RESUL类型的参数,那么可以通过 args->args[i]访问该字符串,字符串的长度是args->lengths[i](不要假定该字符串是以null结尾的)。对于INT_RESULT类型的参数,通过long long int_val = *((long long*) args->args[i]);进行访问。对于REAL_RESULT类型参数,通过double real_val = *((double*) args->args[i]);进行访问。对于DECIMAL_RESULT类型参数,处理方式同STRING_RESULT。
  • unsigned long *lengths。在xxx_init()函数中,其值是字符串参数的最大长度。在xxx()函数中,其值是字符串参数的实际长度。对于INT_RESULT 或者REAL_RESULT类型参数,其值始终是最大可能值。
  • char *maybe_null。在xxx_init()函数中,其值表明该参数是否可以为null。
  • char **attributes。参数名。默认情况下是SQL中的表达式文本(同样,不要假定该字符串是以null结尾的)。
  • unsigned long *attribute_lengths。参数名的字符串长度。

    以下是个UDF C代码的片段:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include "mysql.h"

///////////////////////////////////////////////////
extern "C" { 
    //
    my_bool send_message_open_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
    char * send_message_open(UDF_INIT *initid, UDF_ARGS *args, char* result, unsigned long *length, char *is_null, char *error);
    void send_message_open_deinit(UDF_INIT *initid);

    //
    my_bool send_message_close_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
    char * send_message_close(UDF_INIT *initid, UDF_ARGS *args, char* result, unsigned long *length, char *is_null, char *error);
    void send_message_close_deinit(UDF_INIT *initid);
    
    //
    my_bool send_message_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
    char * send_message(UDF_INIT *initid, UDF_ARGS *args, char* result, unsigned long *length, char *is_null, char *error);
    void send_message_deinit(UDF_INIT *initid);
}

////////////////////////////////////////////////////
// Open
////////////////////////////////////////////////////
my_bool send_message_open_init(UDF_INIT *initid, UDF_ARGS *args, char *message) {
    // Validation
    if(args->arg_count != 2) {
        strcpy(message,"usage: select send_message_open('10.15.3.68', 7777)");
        return -1;
    } else if(args->arg_type[0] != STRING_RESULT || args->arg_type[1] != INT_RESULT){
        strcpy(message,"usage: select send_message_open('10.15.3.68', 7777)");
        return -1;
    } else {
        return 0;
    }
}

char * send_message_open(UDF_INIT *initid, UDF_ARGS *args, char* result, unsigned long *length, char *is_null, char *error){
    ...
}

void send_message_open_deinit(UDF_INIT *initid) {
}

...

 

    编译:

    g++ -I/usr/local/mysql/include/mysql/ -shared -o send_message.so send_message.c

    编译后需要将so文件拷贝到MySQL可以加载的位置,如:
    cp send_message.so /usr/local/mysql6320/lib/mysql/plugin/

 

    在MySQL中创建UDF:

DROP FUNCTION IF EXISTS send_message_open;
DROP FUNCTION IF EXISTS send_message_close;
DROP FUNCTION IF EXISTS send_message;
CREATE FUNCTION send_message_open RETURNS STRING SONAME 'send_message.so'; 
CREATE FUNCTION send_message_close RETURNS STRING SONAME 'send_message.so'; 
CREATE FUNCTION send_message RETURNS STRING SONAME 'send_message.so'; 

 

    测试:

select send_message_open('10.15.3.68', 7777);
select send_message('test message');
select send_message_close();
8
0
分享到:
评论

相关推荐

    lib_mysqludf_sys 的win版本dll库

    "lib_mysqludf_sys 的win版本dll库"这一标题明确指出,我们正在讨论的是一个专为Windows操作系统设计的动态链接库(Dynamic Link Library, DLL)文件,名为lib_mysqludf_sys。DLL是Windows系统中用于封装可重用代码...

    lib_mysqludf_sys

    《MySQL系统命令UDF——lib_mysqludf_sys详解》 MySQL是一种广泛使用的开源关系型数据库管理系统,其功能强大,灵活性高。在实际应用中,有时我们需要执行一些操作系统级别的任务,如读取或写入文件、执行系统命令...

    MYSQL_UDF-5.0.rar_mysql udf_udf_udf mysql

    MySQL UDF(User Defined Function)是MySQL数据库系统中的一种扩展机制,允许用户自定义函数以满足特定的计算或处理需求。这些自定义函数通常用C或C++编写,然后编译为动态链接库(DLL),供MySQL服务器调用。本...

    CentOS 7.5 64下编译好的lib_mysqludf_sys.so

    CentOS 7.5 64位下编译好的lib_mysqludf_sys.so,源文件在https://download.csdn.net/download/shaynerain/10715798,我博客 中有介绍怎么用

    lib_mysqludf_json-master.zip

    `lib_mysqludf_json`是一个用户定义的函数(User Defined Function, UDF)库,它提供了在MySQL中操作JSON数据的能力。本篇文章将深入探讨`lib_mysqludf_json`库的功能、安装方法以及如何利用其将MySQL数据映射为JSON...

    mysqludf库

    `mysqludf库`特别是`lib_mysqludf_sys`是这个领域的一个常见插件,它使用户能够直接在SQL查询中调用操作系统级别的命令,极大地提高了数据处理的灵活性。 `lib_mysqludf_sys`库由一系列C语言编写的共享库组成,这些...

    mysql udf提权文件

    mysql udf提权文件mysql udf提权文件

    mysql-udf-http下载

    MySQL UDF (User Defined Function) 是 MySQL 数据库系统中的一种扩展机制,允许用户自定义函数以处理特定的数据操作。在本场景中,`mysql-udf-http` 是一个特殊的 UDF 库,它为 MySQL 提供了通过 HTTP 协议进行数据...

    如何利用Debugview方式来调试MySQL UDF

    调试MySQL的用户自定义函数(UDF)是一个关键任务,特别是在开发或优化这些函数时。UDF是MySQL中用于扩展数据库功能的动态链接库(DLL),在*Nix系统中称为共享库。通常,调试DLL涉及复杂的步骤,但通过使用Debugview...

    mysql udf c文件

    MySQL UDF(User Defined Function)是指用户自定义函数,它允许开发者使用C或C++语言扩展MySQL的功能,创建个性化的数据库操作。这个压缩包包含了针对不同操作系统平台的MySQL UDF C语言源码,包括Windows 32位和64...

    一个高性能 mysql udf,用于将新修改,插入的数据从 mysql 同步到 redis 缓存 .zip

    依赖项请下载以下依赖项并正确编译/安装apr-1.4.6(http://apr.apache.org/download.cgi)apr-util-1.5.2(http://apr.apache.org/download.cgi)hiredis( https://github.com/redis/hiredis )lib_mysqludf_json...

    MYSQL的UDF开发的资源文件

    MySQL的UDF(User Defined Function)是数据库系统中一个非常重要的特性,它允许用户自定义函数,以扩展MySQL的功能。UDF开发可以帮助开发者根据特定需求定制功能,解决标准SQL无法满足的问题。本资源文件可能包含了...

    mysqludf接口编程示例借鉴.pdf

    MySQL UDF(User Defined Function)接口编程是一种扩展MySQL数据库功能的方法,允许开发人员自定义函数以处理特定的数据操作。在本示例中,我们探讨如何创建一个MySQL UDF,该函数能够向指定的IP地址和端口POST数据...

    mysql提权udf

    MySQL UDF(User Defined Function)是指用户自定义函数,它允许开发者扩展MySQL数据库系统的功能,创建自己的函数以处理特定的数据操作。在网络安全领域,"mysql提权udf"常常指的是利用UDF进行权限提升的技巧,这...

    lib_mysqludf_sys_0.0.3.rar_杩涚▼ 璺緞

    标题中的“lib_mysqludf_sys_0.0.3.rar”是一个压缩文件,其中包含了“lib_mysqludf_sys”库的版本0.0.3。这个库是专门为MySQL数据库设计的用户定义函数(UDF)集合,允许在SQL查询中执行特定的操作,比如与操作系统...

    lib_mysqludf_http:http 获取、发布、放置和删除

    lib_mysqludf_http http 获取、发布、放置和删除 构建 mingw 版本的 curl (C:\curl-7.41.0) (mingw32-make.exe mingw32) 确保 libcurl.dll 在系统路径中(mysql 运行所在的用户和路径 env) 用于构建 DLL 的 Mingw...

    mysqludf-neokylin.x86_64.zip

    yum install mysqludf-neokylin.x86_64.rpm [root@localhost ~]# find /usr -name lib_mysqludf_sys.so /usr/lib64/mysql/plugin/lib_mysqludf_sys.so

    mysql-udf-http

    MySQL UDF (User Defined Function) 是 MySQL 数据库系统中一个非常重要的特性,它允许用户自定义函数来扩展数据库的功能。"mysql-udf-http" 是一个特定的 UDF 库,专门为 MySQL 设计,用于在 SQL 查询中直接执行 ...

    mysql-udf-http.c

    mysql-udf-http.c编译此文件之后可使用MySQL中http_post或http_get方法,此处为原文件,需要自行编译,请谨慎下载。备注:如发现此文件编译时缺少文件可自行下载

    lib_mysqludf_log:将调试信息写入日志文件的 UDF 库

    LIB_MYSQLUDF_LOG 从 SQL 语句或存储过程内部写入日志文件通常很有用。 目前这个库只包含一个允许你写入错误日志文件的函数。 该库 lib_mysqludf_log 可用于将调试信息写入日志文件。 目前支持以下功能: log_...

Global site tag (gtag.js) - Google Analytics