试玩HandlerSocket for MySQL

有这么一个场景,单台MySQL数据库服务器,最大表约500万记录,常用表100万记录,每行记录的数据量不是很大
查询还算频繁,插入修改删除数据不是那么多,多个应用同时访问这个数据库
有个应用就是查询为主,没有修改,少量的删除
查询SQL语句很简单,根据用户ID查询他下面的记录(某些字段),根据记录ID查询整条记录,两表关联查询100万的关联500万
目前应用的实现也很简单,简陋的数据库连接池,客户端发送SQL语句到SQL服务器
现在也没有遇到很大的问题,没有宕机什么的问题,但就是客户端反映慢,但是看服务器的负载都不是很高

所以老大就说太慢了,需要解决

这个慢是比较显然的啊,每次解析执行SQL语句,网络传输,数据库服务器内存较小,缓存不够

所以当然就想到了在应用层加缓存,但是在几个月之前曾经看到过HandlerSocket的简单介绍,只知道它可以加快查询,没有细看

所以突然觉得目前这个也可以改用HandlerSocket,而且更合适,向老大建议,当然建议都是木有用的,因为我做不鸟主,老大有老大的想法

所以只能自己研究看看这个东西适合不了

于是就开始下载编译安装这个东西了,步骤还算简单

具体安装参见installation.en.txt

我开始想用5.1的源码和5.5的二进制版本混合编译(目前我自己用的5.5的MySQL),天知道能不能成功(最后是不能成功的,我又用5.1的源码重新编译了一个MySQL数据库出来,然后编译HandlerSocket并把它安装到5.1中了,后来看到介绍是源码版本一定要和当前安装的数据库的版本一致,之所以需要源码是因为HandlerSocket插件用到了MySQL源码之中的几个头文件之类的吧,总之不看README是很头疼的。比如有的酒店的电梯是要用房卡刷了电梯之后才能按楼层的,README写的清清楚楚,汗)
我的编译步骤如下
$ ./autogen.sh
$ ./configure –with-mysql-source=/home/guohai/dev/src/database/mysql-5.1.57 –with-mysql-bindir=/home/guohai/dev/a/mysql/mysql-5.1.57-linux2.6-i686/bin –with-mysql-plugindir=/home/guohai/dev/a/mysql/mysql-5.1.57-linux2.6-i686/lib/mysql/plugin

$ make
$ sudo make install

mysql> install plugin handlersocket soname ‘handlersocket.so’;
Query OK, 0 rows affected (0.03 sec)

mysql> show plugins;
+—————+——–+—————-+——————+———+
| Name | Status | Type | Library | License |
+—————+——–+—————-+——————+———+
| binlog | ACTIVE | STORAGE ENGINE | NULL | GPL |
| partition | ACTIVE | STORAGE ENGINE | NULL | GPL |
| CSV | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MEMORY | ACTIVE | STORAGE ENGINE | NULL | GPL |
| InnoDB | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MyISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MRG_MYISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |
| handlersocket | ACTIVE | DAEMON | handlersocket.so | BSD |
+—————+——–+—————-+——————+———+
8 rows in set (0.00 sec)

这样插件就安装好了,接下来就是装个客户端试试看了,用的淘宝的那个

当然还要在my.cnf中增加类似参数
loose_handlersocket_port = 9998
# the port number to bind to (for read requests)
loose_handlersocket_port_wr = 9999
# the port number to bind to (for write requests)
loose_handlersocket_threads = 16
# the number of worker threads (for read requests)
loose_handlersocket_threads_wr = 1
# the number of worker threads (for write requests)
open_files_limit = 65535
# to allow handlersocket accept many concurrent
# connections, make open_files_limit as large as
# possible.

弄hs4j还是报了几个错误,什么open_table,原因是我表名没有写对,巨汗,不过这个提示也够瓜的
估计也是我没有理解这个东西

然后我又报了个错误
Exception in thread “main” com.google.code.hs4j.exception.HandlerSocketException: Connection has been closed
at com.google.code.hs4j.impl.HSClientImpl.awaitResponse(HSClientImpl.java:417)
at com.google.code.hs4j.impl.HSClientImpl.insert0(HSClientImpl.java:325)
at com.google.code.hs4j.impl.HSClientImpl.insert(HSClientImpl.java:309)
at com.google.code.hs4j.example.HS4JExample.main(HS4JExample.java:29)
这个我把keys写少了一个,所以报错了
总之都是我的问题

就这样解决几个问题之后客户端就基本可用了

然后我还试了下Python的客户端,装好Python的插件http://packages.python.org/python-handler-socket/
就可以开始玩了,照着例子也很简单

看了还算多的文章介绍以及issues,这个东西在某些特定的情况下还是可以开始用的吧,以前提的比较多的问题,什么auto_increment之类的也都解决了

觉得最关键的是就是参数怎么配置,才能让这个东西在需要的场景下发挥最大的能力

还得多看看,多试试才有更充分的把握

参考
https://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL
http://yoshinorimatsunobu.blogspot.com/2010/10/using-mysql-as-nosql-story-for.html 你懂的
https://github.com/killme2008/hs4j
http://whitesock.iteye.com/blog/811339
http://rdc.taobao.com/team/jm/archives/545
http://www.cnblogs.com/inrie/archive/2011/01/28/1946572.html 系列文章
http://huoding.com/2011/04/10/62

流水帐总是很简单,再把编译MySQL的主要过程也记在这里吧,凑点字数
我用的是Ubuntu 10.10 X86,以前编译过很多软件开发包,所以如果编译的时候遇到缺什么包装上就行了
下载就不说了,下载都不会的就不要从源码编译了,我用的是mysql-5.1.57.tar.gz
编译参见INSTALL-SOURCE
2.11.2. Installing MySQL from a Standard Source Distribution

$ ./configure –prefix=/home/guohai/dev/a/mysql/mysql-5.1.57-linux2.6-i686 –with-unix-socket-path=/tmp/mysql51.sock –with-tcp-port=3307 –with-named-curses-libs=/lib/libncurses.so.5 –enable-assembler –with-plugins=partition,innobase –with-charset=utf8 –with-collation=utf8_general_ci –with-extra-charsets=big5,ascii,gbk,utf8,latin1 –with-big-tables –without-debug

$ make
$ make install

$ cd /home/guohai/dev/a/mysql/mysql-5.1.57-linux2.6-i686
$ chown -R mysql .
$ chgrp -R mysql .

我以前已经装过MySQL5.5所以这些用户以及组都是有的

guohai@KNIGHT:~/dev/a/mysql/mysql-5.1.57-linux2.6-i686$ sudo cp ‘/home/guohai/dev/src/database/mysql-5.1.57/support-files/my-medium.cnf’ ./my.cnf

$ sudo bin/mysql_install_db –user=mysql –basedir=/home/guohai/dev/a/mysql/mysql-5.1.57-linux2.6-i686 –datadir=/home/guohai/dev/a/mysql/mysql-5.1.57-linux2.6-i686/data

启动数据库
$ sudo bin/mysqld_safe –defaults-file=/home/guohai/dev/a/mysql/mysql-5.1.57-linux2.6-i686/my.cnf –user=mysql &
注意这个参数传递的顺序,我开始一直把–user=mysql放前面,启动的时候报错,MySQL日志记载unknown variable ‘defaults-file’
110601 23:23:28 [ERROR] /home/guohai/dev/a/mysql/mysql-5.1.57-linux2.6-i686/libexec/mysqld: unknown variable ‘defaults-file=/home/guohai/dev/a/mysql/mysql-5.1.57-linux2.6-i686/my.cnf’
110601 23:23:28 [ERROR] Aborting
110601 23:23:28 InnoDB: Starting shutdown…
110601 23:23:33 InnoDB: Shutdown completed; log sequence number 0 44233
110601 23:23:33 [Note] /home/guohai/dev/a/mysql/mysql-5.1.57-linux2.6-i686/libexec/mysqld: Shutdown complete

然后看了mysqld_safe下这个脚本的写法,发现它有对传入的第一个参数判断是否为defaults,于是我就把defaults-file这个参数放到第一位,就正常启动了

一切都好了,然后就是设置了
/home/guohai/dev/a/mysql/mysql-5.1.57-linux2.6-i686$ sudo bin/mysql_secure_installation
一步步来就好了,注意默认my.cnf的位置,我的就放在mysql-5.1.57安装目录下

可能还要修改下MySQL数据文件存放的路径,我最开始编译的时候没有指定,然后它帮我生成的是放在mysql-5.1.57安装目录的一个var目录下面的,而我在my.cnf中指定的是data目录
所以我就修改了一个脚本中的,把var改为data了,具体是哪个脚本忘记了

再重启下,就可以用mysql命令连接上去了,基本正常

MySQL编译简单,关键是编译出自己想要的MySQL,编译出符合自己业务高性能的MySQL就是技术活了,参数很关键
只要参数用的好,没有程序写不鸟;只要工具用的好,没有程序写不鸟;夸张了点

还有刚开始编译出来你可能找不到mysqld这个东西,我反正一开始是没有找到,以为自己编译的出错了,后来才发现在libexec下而不是在bin下面,多用用工具搜索搜索就出来了

另外也可以参见Ubuntu二进制安装MySQL 5.5
地址http://lucane.iteye.com/blog/866355

13 thoughts on “试玩HandlerSocket for MySQL”

  1. 我想问下,为什么我按照你那么弄编译不过呢?是不是要先安装了mysql啊,方便留下您的qq么?

  2. @winkyLin
    是的,先要装MySQL,编译HandlerSocket还要有MySQL的源码,并且MySQL源码和已经装好的MySQL的版本要一致
    你看看文章中写的“具体安装参见installation.en.txt”后面的这部分

    还有当中给的些链接也很有用,我都是照着别人的弄出来的

    或者你有什么问题也可以回帖,把错误日志之类的贴上,怎么操作的
    我会尽快回复的

  3. 你是MySQL程序没有装成功?
    我这篇文章当中的MySQL是从源码编译出来的
    mysql_install_db是用来安装基本的数据库实例的,比如自带的mysql,information_schema和test库
    mysql_install_db一般位于MYSQL_HOME/bin这个目录下

    不管是从源码编译出来的,还是直接从二进制分发版安装的都应该有这个文件
    实在不行,你留下QQ什么的,我加你吧。。。

    这个http://lucane.iteye.com/blog/866355是从二进制安装MySQL的过程

  4. 很悲剧.. 我安装好了..

    mysql 版本 5.1.57..

    之后安装phpext..

    php调试的提示过几个错误之后.. 没有错误了.. 但是它不返回任何信息..

    这是怎么回事..

    require_once(‘HSMysql.php’);
    $hs = new HSMysql(‘message’);
    $data = $hs->query(‘id,message’,’PRIMARY’,’=’,array(3),50);
    print_r($data);
    调用部分

    类里面
    public function query($columns, $index, $operation, $fields, $number, $skip=0){
    $db = $this->getInstance();
    $this->openIndex(1, $db, $index, $columns);
    $res = $db->executeSingle(1, $operation, $fields, $number, $skip);
    if($res === false){
    echo $db->getError();
    exit();
    }
    $this->_data = $res;
    return $this;
    }


    public function openIndex($id, $db, $index = ”, $columns){

    if (!$db->openIndex($id, DB_NAME, $this->_table, $index, $cls)){
    echo $db->getError();
    exit();
    }
    return true;
    }这个是query方法调用的openIndex

      1. 最后测试 插入数据 可以插入但是目标字段是空值
        更新数据.. 刷新没提示没反应 也没更新

        1. 什么叫目标字段是空值?PHP客户端没有尝试过,我试过Java,Python,C++客户端,应该是可以的吧
          不过有些错误信息提示确实不够清楚

Leave a Reply

Your email address will not be published. Required fields are marked *