MySQL用户自定义函数

  从很早开始,MySQL就支持用户自定义函数(UDF)。存储过程只能使用SQL来编写,而UDF没有这个限制,你可以使用支持C语言调用约定的任何编程语言来实现。

  UDF必须事先编译好并动态链接到服务器上,这种平台相关性使得UDF在很多方面都很强大。UDF速度非常快,而且可以访问大量操作系统的功能,还可以使用大量库函数。使用SQL实现的存储函数在实现一些简单操作上很有优势,诸如计算球体上两点之间的距离,但是如果操作涉及到网络交互,那么只能使用UDF了。同样地,如果需要一个MySQL不支持的统计聚合函数,而且无法使用SQL编写的存储函数来实现的话,通常使用UDF是很容易实现的。

  能力越大,责任越大。所以在UDF中的一个错误很可能会让服务器直接崩溃,甚至扰乱服务器的内存或者数据,另外,所有C语言具有的潜在风险,UDF也都有。

  提示:和使用SQL语言编写存储程序不同,UDF无法读写数据表——至少,无法在调用UDF的线程中使用当前事务处理的上下文来读写数据表。这意味着,它更适合用作计算或者与外面的世界交互。MySQL已经支持越来越多的方式和外面的资源交互了。Brian Aker和Patrick Galbraith创建的与memcached通信的函数就是一个UDF很好的案例。

  如果打算使用UDF,那么在MySQL版本升级的时候需要特别注意做相应的改变,因为很可能需要重新编译这些UDF,或者甚至需要修改UDF来让它能在新的版本中工作。还需要注意的是,你需要确保UDF是线程安全的,因为它们需要在MySQL中执行,而MySQL是一个纯粹的多线程环境。

  现在已经有很多写好的UDF直接提供给MySQL使用,还有很多UDF的示例可供参考, 以便完成自己的UDF。现在UDF最大的仓库是http://www.mysqludf.org。

  下面是一个用户自定义函数NOW_USEC()的代码:

#include <my_global.h>
#include <my_sys.h>
#include <mysql.h>
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
extern "C" {
   my_bool now_usec_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
   char *now_usec(
                  UDF_INIT *initid,
                  UDF_ARGS *args,
                  char *result,
                  unsigned long *length,
                  char *is_null,
                  char *error);
}
my_bool now_usec_init(UDF_INIT *initid, UDF_ARGS *args, char *message) {
   return 0;
}
char *now_usec(UDF_INIT *initid, UDF_ARGS *args, char *result,
               unsigned long *length, char *is_null, char *error) {
  struct timeval tv;
  struct tm* ptm;
  char time_string[20]; /* e.g. "2006-04-27 17:10:52" */
  char *usec_time_string = result;
  time_t t;
  /* Obtain the time of day, and convert it to a tm struct. */
  gettimeofday (&tv, NULL);
  t = (time_t)tv.tv_sec;
  ptm = localtime (&t);
  /* Format the date and time, down to a single second. */
  strftime (time_string, sizeof (time_string), "%Y-%m-%d %H:%M:%S", ptm);
  /* Print the formatted time, in seconds, followed by a decimal point
   * and the microseconds. */
  sprintf(usec_time_string, "%s.%06ld\n", time_string, tv.tv_usec);
  *length = 26;
  return(usec_time_string);
}

  参考前一章中的案例学习,可以看到如何使用用户自定义函数来解决一些棘手的问题。在Percona Toolkit中也使用了UDF来完成一些工作,例如髙效的数据复制校验,或者在Sphinx索引之前使用UDF来预处理一些问题等。UDF是一款非常强大的工具。

 

posted @ 2021-11-13 18:41  小家电维修  阅读(137)  评论(0编辑  收藏  举报