Ubuntu 安装 Mysql2redis 及错误日记

Summary: Author: 张亚飞 | 阅读时间: 5 minute read | Published: 2016-08-08
Filed under Categories: DevOpsTags: Linux, Server, Software, DevOps,

mysql2redis 是 Mysql 的一个 UDF(user-defined function) 函数,它提供了 mysqlredis 之间的数据交互.当 mysql 的数据进行了更新,它就会调用相应 的 trigger 调用 mysql2redis 里面的函数对 redis 的数据进行更新.

安装前提

安装 mysql2redis 前,先在系统里安装 mysql, redis 并安装相关依赖:

jemalloc
apr 和 apr-util
hiredis
lib_mysqludf_json

安装过程–Ubuntu

安装 jemalloc

sudo apt install libjemalloc1 libjemalloc-dev -y

安装 aprapr-util

aprapr-util 是两个依赖包,它们最新版本的下载地址请点击,下载 好的以后,它的安装过程如下(配制,编译,安装):

wget http://mirrors.hust.edu.cn/apache//apr/apr-1.6.5.tar.gz
sudo tar zxvf apr-1.6.5.tar.gz
cd apr-1.6.5
./configure
make
make test
sudo make install

完成编译后将会创建 /usr/local/apr 目录下

wget http://mirrors.hust.edu.cn/apache//apr/apr-util-1.6.1.tar.gz
tar zxvf apr-util-1.6.1.tar.gz
cd apr-util-1.6.1
./configure --with-apr=/usr/local/apr
make
sudo make install

完成编译后将会将 apr-util 添加至 /usr/local/apr/lib 目录下

注:编译完以上两个源码,需要将生成的 /usr/local/apr/lib/libapr-1.so.0/usr/local/apr/lib/libaprutil-1.so.0 拷贝到 /usr/lib/x86_64-linux-gnu/

cp /usr/local/apr/lib/libapr-1.so.0 /usr/lib/x86_64-linux-gnu/libapr-1.so.0
cp /usr/local/apr/lib/libaprutil-1.so.0 /usr/lib/x86_64-linux-gnu/libaprutil-1.so.0

lib_mysqludf_json 是一个支持 json 数据格式的UDF函数,它提供给 mysqlredis 进行数据交互.它的下载安装过程如下:

sudo git clone https://github.com/mysqludf/lib_mysqludf_json.git
cp lib_mysqludf_json.so /usr/lib/mysql/plugin

hiredisredis 的一个调用接口,它提供了一些简单的 redis 的操作,它 的安装和下载过程如下:

sudo git clone https://github.com/redis/hiredis.git
cd hiredis
make
sudo make install

完成编译后将会创建 /usr/local/include/hiredis//usr/local/lib/libhiredis.so 文件

将生成的 /usr/local/lib/libhiredis.so.0.13 文件拷备到 /lib/libhiredis.so.0.13

貌似不用将生成的 libhiredis.so 拷贝到 /usr/lib/mysql/plugins 下,

  • 最后安装 mysql2redis
sudo git clone https://github.com/dawnbreaks/mysql2redis.git
cd mysql2redis
make
sudo make install

最后 make install 会将当前目录下生成的 lib_mysqludf_redis_v2.so 文件复制到 mysqlplugin_dir

注:另有一个类似库 https://github.com/aborn/mysql2redis.git

下载完 mysql2redis 后,记住修改以下几步:

  • 修改 Makefile 将默认 /usr/lib64/mysql/plugin 修改为当前系统的 /usr/lib/mysql/plugin (修改 PLUGINDIR 参数 添加 mysqlinclude-I/usr/include/mysql)并重新编译安装

  • 编译 make 的时候提示错误,貌似没有找到 my_global.h 文件

/bin/sh: 1: /usr/bin/mysql_config: not found
In file included from lib_mysqludf_redis.c:5:0:
lib_mysqludf_redis.h:21:23: fatal error: my_global.h: No such file or directory
#include <my_global.h>

发现没有 Makefile 里指定的 /usr/include/mysql 文件,查看之前的服务器,发现存在并且里边包含有 my_global.h 文件,于是猜是这里出了问题,一番搜索之后,提示需要安装mysql开发包

sudo apt install libmysqlclient-dev

发现已创建此目录,重新编译没有提示上面的错误

  • 注意,在 Ubuntu16.04 中,安装的 libmysqlclient-dev(libmysqlclient20) 后与在 Ubuntu14.04 中版本不一致 libmysqlclient-dev(libmysqlclient18),执行 mysql2redis > make 后出现如下两条错误: yafer@yafer-pc:/opt/data/mysql2redis$ make gcc -Werror -O2 -g `/usr/bin/mysql_config --include` -I/usr/local/include -I/usr/local/apr/include -I./ -I. -fPIC -shared -rdynamic lib_mysqludf_redis.c -lhiredis -L"/usr/lib/mysql/plugin" -L/usr/local/apr/lib -lapr-1 -laprutil-1 -o lib_mysqludf_redis_v2.so In file included from /usr/include/mysql/mysql/services.h:26:0, from /usr/include/mysql/mysql/plugin.h:59, from lib_mysqludf_redis.h:40, from lib_mysqludf_redis.c:5: /usr/include/mysql/mysql/service_srv_session_info.h:31:53: fatal error: violite.h: No such file or directory compilation terminated. Makefile:6: recipe for target 'compile' failed make: *** [compile] Error 1 yafer@yafer-pc:/opt/data/mysql2redis$ make gcc -Werror -O2 -g `/usr/bin/mysql_config --include` -I/usr/local/include -I/usr/local/apr/include -I./ -I. -fPIC -shared -rdynamic lib_mysqludf_redis.c -lhiredis -L"/usr/lib/mysql/plugin" -L/usr/local/apr/lib -lapr-1 -laprutil-1 -o lib_mysqludf_redis_v2.so In file included from /usr/include/mysql/mysql/services.h:43:0, from /usr/include/mysql/mysql/plugin.h:59, from lib_mysqludf_redis.h:40, from lib_mysqludf_redis.c:5: /usr/include/mysql/mysql/service_parser.h:19:25: fatal error: my_md5_size.h: No such file or directory compilation terminated. Makefile:6: recipe for target 'compile' failed make: *** [compile] Error 1

大概是指 /usr/include/mysql/mysql/services.h 中包含的 service_srv_session_info.hservice_parser.h 中的文件错误

修改 /usr/include/mysql/mysql/services.h 并注释掉以下两行:

//[/usr/include/mysql/mysql/services.h-Line:26]//#include <mysql/service_srv_session_info.h>
//[/usr/include/mysql/mysql/services.h-Line:43]//#include <mysql/service_parser.h>

重新 make 编译 mysql2redis 即可顺利通过

sudo apt install libmysqlclient-dev
sudo apt install libmysql++-dev
Tue May 30 21:54:38 coam@ms:/usr/local/mysql$ sudo find / -name services.h
/usr/include/mysql/mysql/services.h
/usr/local/mysql/include/mysql/services.h

注意:实际统一修改 /usr/local/mysql/include/mysql/services.h Mysql 源码编译的库文件…

  • 错误 lib_mysqludf_redis.c:271:13: error: format not a string literaland no format arguments

将 lib_mysqludf_redis.c [Line:271]行的 fprintf(pFile, buf) 改为 fputs(buf, pFile),或注释掉 [Line:46] /debug_print(buf);/

MYSQL 的配制

  • 对于 lib_mysqludf_json 在 mysql 中执行以下sql命令:
DROP FUNCTION IF EXISTS json_members;
DROP FUNCTION IF EXISTS json_array;
DROP FUNCTION IF EXISTS json_object;
DROP FUNCTION IF EXISTS json_values;
CREATE FUNCTION json_members RETURNS STRING SONAME 'lib_mysqludf_json.so';
CREATE FUNCTION json_array RETURNS STRING SONAME 'lib_mysqludf_json.so';
CREATE FUNCTION json_object RETURNS STRING SONAME 'lib_mysqludf_json.so';
CREATE FUNCTION json_values RETURNS STRING SONAME 'lib_mysqludf_json.so';
  • json_array json_object
mysql> CREATE FUNCTION json_array RETURNS STRING SONAME 'lib_mysqludf_json.so';
ERROR 1585 (HY000): This function 'json_array' has the same name as a native function

注:自Mysql5.7开始已有内建 json_array json_object 方法,虽然用法不一样,但是可以稍作调整替换这里的同名方法–所以 lib_mysqludf_json 该库可以不用了

  • 对于 mysql2redis 在 mysql 中执行以下 sql 命令:
DROP FUNCTION IF EXISTS redis_servers_set_v2;
CREATE FUNCTION redis_servers_set_v2 RETURNS int SONAME "lib_mysqludf_redis_v2.so";

DROP FUNCTION IF EXISTS redis_command_v2;
CREATE FUNCTION redis_command_v2 RETURNS int SONAME "lib_mysqludf_redis_v2.so";

DROP FUNCTION IF EXISTS redis_command_v3;
CREATE FUNCTION redis_command_v3 RETURNS int SONAME "lib_mysqludf_redis_v2.so";

DROP FUNCTION IF EXISTS free_resources;
CREATE FUNCTION free_resources RETURNS int SONAME "lib_mysqludf_redis_v2.so";
  • 查看当前创建的用户自定义方法
mysql> select name,dl from mysql .func;
  • 测试: select redis_servers_set_v2("127.0.0.1",6379); select redis_command_v2("hset","hkey","hfield",json_object("op","insert","value","valuettt"));

在安装过程中遇到的问题,请参照 mysql2redis.md

  • 创建 redis_servers_set_v2 FUNCTION 出现如下错误 ‘lib_mysqludf_redis_v2.so’ (errno: 2 libapr-1.so.0: cannot open shared object file
mysql> CREATE FUNCTION redis_servers_set_v2 RETURNS int SONAME "lib_mysqludf_redis_v2.so";
ERROR 1126 (HY000): Can't open shared library 'lib_mysqludf_redis_v2.so' (errno: 2 libapr-1.so.0: cannot open shared object file: No such file or directory)
mysql> CREATE FUNCTION redis_servers_set_v2 RETURNS int SONAME "lib_mysqludf_redis_v2.so";
ERROR 1126 (HY000): Can't open shared library 'lib_mysqludf_redis_v2.so' (errno: 11 libaprutil-1.so.0: cannot open shared object file: No such file or directory)

查看 libapr-1.so.0libaprutil-1.so.0 均在 /usr/local/apr/lib/

查看已安装好的 Ali 服务器

Thu May 19 10:54:21 coam@coam:/usr/lib/x86_64-linux-gnu$ sudo find / -name libapr-1.so.0
/usr/local/apr/lib/libapr-1.so.0
/usr/lib/x86_64-linux-gnu/libapr-1.so.0
...

可以看到 libapr-1.so.0libaprutil-1.so.0 都已复制到系统的 /usr/lib/x86_64-linux-gnu/ 路径下,可能是当前服务器 Vultr 系统安装有差异,于是手动复制这两个文件,问题解决

cp /usr/local/apr/lib/libapr-1.so.0 /usr/lib/x86_64-linux-gnu/libapr-1.so.0
cp /usr/local/apr/lib/libaprutil-1.so.0 /usr/lib/x86_64-linux-gnu/libaprutil-1.so.0
  • 最后登陆 Mysql 命令行测试 redis udf
# 设定连接 Redis 数据库
select redis_servers_set_v2("127.0.0.1", 6379);
select redis_command_v2("HSET","AccountInfoList","C-1",json_object("C-1", "C-1")); // 测试连接

select redis_command_v2("hset","hkey","hfield",json_object(json_members("op","insert","value","valuettt"))); // 测试 json_object 方法
select free_resources();
  • 一次阿里云服务器不能 CREATE FUNCTION redis_servers_set_v2 并报错
mysql> DROP FUNCTION IF EXISTS redis_servers_set_v2;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> CREATE FUNCTION redis_servers_set_v2 RETURNS int SONAME "lib_mysqludf_redis_v2.so";
ERROR 1125 (HY000): Unknown error 1125

之前是可以的,但是现在突然出现问题,折腾了一天重装 mysql 等都没有解决,也不能查看执行这两条 sql 的错误日志,后来通过重启 mysql 查看 /data/home/data/mysql/coam.err 发现如下两条几条错误

* [ERROR] Can't open shared library 'lib_mysqludf_redis_v2.so' (errno: 0 libapr-1.so.0: cannot open shared object file: No such file or directory)
2016-08-01T12:13:36.368731Z 0 [ERROR] Can't open shared library 'lib_mysqludf_redis_v2.so' (errno: 0 libapr-1.so.0: cannot open shared object file: No such file or directory)
2016-08-01T12:13:36.368954Z 0 [ERROR] Can't open shared library 'lib_mysqludf_redis_v2.so' (errno: 0 libapr-1.so.0: cannot open shared object file: No such file or directory)

与前面出现的错误一致,只是现在没有在 sql 下显示该错误,于是仿照之前的问题处理方式解决尝试该问题

Mon Aug 01 20:13:37 coam@coam:/etc/mysql$ cd /usr/local/apr/lib/
Mon Aug 01 20:14:59 coam@coam:/usr/local/apr/lib$ ls
apr.exp      libapr-1.a   libapr-1.so    libapr-1.so.0.5.2  libaprutil-1.la  libaprutil-1.so.0      pkgconfig
aprutil.exp  libapr-1.la  libapr-1.so.0  libaprutil-1.a     libaprutil-1.so  libaprutil-1.so.0.5.4
Mon Aug 01 20:15:00 coam@coam:/usr/local/apr/lib$ sudo find / -name libapr-1.so.0
/usr/local/apr/lib/libapr-1.so.0
/data/run/mysql2redis/apr-1.5.2/.libs/libapr-1.so.0
/opt/data/apr-1.5.2/.libs/libapr-1.so.0

可以看到 libapr-1.so.0libaprutil-1.so.0 已不在系统的 /usr/lib/x86_64-linux-gnu/ 路径下,于是手动复制这两个文件,问题解决(可能是执行了什么 sudo apt autoremove 系统自动删除了这两个文件吧,以后要定期检查这个目录的两个so文件)

cp /usr/local/apr/lib/libapr-1.so.0 /usr/lib/x86_64-linux-gnu/libapr-1.so.0
cp /usr/local/apr/lib/libaprutil-1.so.0 /usr/lib/x86_64-linux-gnu/libaprutil-1.so.0
  • 编译项目时提示如下错误:
/usr/bin/ld: cannot find -lapr-1
/usr/bin/ld: cannot find -laprutil-1
  • 按以下方式添加系统编译搜索路径
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/apr/lib/

重启 Mysql 恢复,可重新执行

mysql> DROP FUNCTION IF EXISTS redis_servers_set_v2;
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE FUNCTION redis_servers_set_v2 RETURNS int SONAME "lib_mysqludf_redis_v2.so";
Query OK, 0 rows affected (0.00 sec)

错误记录

  • 错误 lib_mysqludf_json.so: wrong ELF class: ELFCLASS32) 产生原因是: lib_mysqludf_json.so 是32位的文件-解决方法:重新编译
cd /opt/data/lib_mysqludf_json
sudo gcc -Wall -m64 -I/usr/include/mysql -I. -shared lib_mysqludf_json.c -o ./lib_mysqludf_json.so -fPIC

注意:-I 为 mysql 的 include 目录

  • 错误 libhiredis.so.0.10: cannot open shared object file 执行以下命令:
sudo cp /usr/local/lib/libhiredis.so.0.10 /lib
  • Mysql SQL 创建 json_members 方法的时候,提示如下错误:
mysql> CREATE FUNCTION json_members RETURNS STRING SONAME 'lib_mysqludf_json.so';
ERROR 1126 (HY000): Can't open shared library 'lib_mysqludf_json.so' (errno: 2 /usr/local/mysql/usr/lib/mysql/plugin/lib_mysqludf_json.so: cannot open shared object file: No such file or directory)

检查发现 /usr/lib/mysql/plugin/lib_mysqludf_json.so 文件存在,可能是安装 Mysql 配置的 plugin-dir 有问题 /usr/local/mysql/

Sat May 14 18:02:00 coam@coam:/opt/data/mysql2redis$ sudo ps -ef | grep mysql
root       958     1  0 May13 ?        00:00:00 /bin/sh /usr/local/mysql/bin/mysqld_safe --datadir=/data/home/data/mysq  --pid-file=/data/home/data/mysql/coam.pid
mysql     1204   958  0 May13 ?        00:00:19 /usr/local/mysql/bin/mysqld --basedir=/usr/local/mysql --datadir=/data/home/data/mysql --plugin-dir=/usr/local/mysql//usr/lib/mysql/plugin --user=mysql --log-error=/var/log/mysql/error.log --pid-file=/data/home/data/mysql/coam.pid --socket=/var/run/mysqld/mysqld.sock --port=3306
coam    8559 24523  0 18:05 pts/0    00:00:00 mysql -u zhangyanxi -p
coam   12036 29119  0 18:12 pts/4    00:00:00 grep --color=auto mysql

可以看见 –plugin-dir=/usr/local/mysql//usr/lib/mysql/plugin 这里配置有问题

  • 我是 Mysql 源码编译安装,并且在 cmake 中设定参数 *-DINSTALL_PLUGINDIR=/usr/lib/mysql/plugin * 也没有问题.修改 /etc/mysql/my.cnf 添加以下内容
* [mysqld]
plugin_dir=/usr/lib/mysql/plugin

重启 mysql 发现问题已修正

参考列表


Comments

Cor-Ethan, the beverage → www.iirii.com