NoSQLとしてのMySQLの動作確認(HandlerSocket)

やったこと

結論

  • データをセットしたらmysqlがぶっ壊れた(環境構築に問題があった?)
  • getだけで"perlからsingle getで"簡単に性能を測ったらそこそこでた(11300 req/sec)
  • pure C/C++で多重度をあげて測れば75万いくかも?

環境

  • CentOS 5.2
  • memory 4G
  • on VM
  • dual core cpu
model name      : QEMU Virtual CPU version 0.12.3
cpu MHz         : 2792.856
cache size      : 4096 KB

MySQL Server セットアップ

% ./configure \
--with-charset=utf8 \
--with-extra-charsets=all \
--with-mysqld-user=mysql \
--with-\innodb \
--\enable-local-infile \
--\with-unix-socket-path=/tmp/mysql.sock
% make
% sudo make install
% sudo /usr/local/mysql/bin/mysql_install_db
% sudo /usr/local/bin/mysqld_safe &
  • あとは文字コードをUTFにしたり、my.cnfのinnodbのパラメータを調節したり
  • 若干はまったけど、割愛

Handler Socket build

% mkdir ~/git ; cd ~/git
% git clone http://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL.git
% cd git/HandlerSocket-Plugin-for-MySQL/
% ./configure --with-mysql-source=/home/satoshi/src/mysql-5.1.51/ \
--with-mysql-bindir=/usr/local/bin

テーブル作成

CREATE TABLE user (
  id INT NOT NULL PRIMARY KEY,
  name char(32)
) ENGINE=INNODB;

参照の動作確認

  • 以下手順
(mysqlのデータ確認)
mysql> select * from user;
+----+---------+
| id | name    |
+----+---------+
|  1 | tanarky |
|  2 | satoshi |
+----+---------+
2 rows in set (0.00 sec)

(telnetで接続してデータを取得する)
% telnet localhost 9998
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.

# タブ区切り
# "satoshi" database, "user" table, index=3
REQ% P       3       satoshi user    PRIMARY id,name
RES% 0       1

# 上で指定したINDEX(=3)を使って検索する
# INDEX(3), 等しい, 1(?), PRIMARY=1, 1件, offset=0
REQ% 3       =       1       1       1       0
RES% 0       2       1       tanarky

# 上で指定したINDEX(=3)を使って検索する
# INDEX(3), 等しい, 1(?), PRIMARY=2, 1件, offset=0
REQ% 3       =       1       2       1       0
RES% 0       2       2       satoshi
  • 無事にデータが取得できた
  • 便宜上、telnet接続後のリクエストにはREQ%, レスポンスにRES%,を頭につけている
  • # 行はコメントってことで、リクエストの補足を書いている

更新の確認

  • まずはデータの確認
(mysqlのデータ確認)
mysql> select * from user;
+----+---------+
| id | name    |
+----+---------+
|  1 | tanarky |
|  2 | satoshi |
+----+---------+
2 rows in set (0.00 sec)

mysql> select count(*) from user;
+----------+
| count(*) |
+----------+
|        2 |
+----------+
1 row in set (0.00 sec)
  • データをinsertしてみる by telnet
% telnet localhost 9999
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.

# 接続
REQ% P       3       satoshi user    PRIMARY id
RES% 0       1

# id=1を取得(成功)
REQ% 3       =       1       1       1       0
RES% 0       1       1

# id=2を取得(成功)
REQ% 3       =       1       2       1       0
RES% 0       1       2

# id=3を取得(成功、データがないので空)
REQ% 3       =       1       3       1       0
RES% 0       1

# id=3をinsert(失敗?responseにinsertnumがない)
REQ% 3       +       1       3
RES% 0       1
  • mysqlを見てみる
mysql> select * from user;
+----+---------+
| id | name    |
+----+---------+
|  1 | tanarky |
|  2 | satoshi |
+----+---------+
2 rows in set (0.00 sec)

mysql> select count(*) from user;
+----------+
| count(*) |
+----------+
|        3 |
+----------+
1 row in set (0.01 sec)

mysql> select * from user where id = 3;
ERROR 1030 (HY000): Got error 134 from storage engine
  • データがぶっ壊れた
  • telnet経由でも値が取れず
  • perl client経由でも、値のセットとゲットができず(同じように壊れる)

性能測定

  • getのみ
  • perl clientから
  • single get
  • 以下がテストコード(test_client.pl)
use strict;
use warnings;
use Data::Dumper;
use Net::HandlerSocket;
my $args = { host => 'localhost', port => 9999 };
my $hs = new Net::HandlerSocket($args);
my $res = $hs->open_index(3, 'satoshi', 'user', 'PRIMARY', 'id,name');
warn Dumper($res);
for(my $i=0;$i<100000;$i++){
    $res = $hs->execute_single(3, '=', [ '1' ], 1, 0);
}
  • 実行結果(8秒後半-12秒弱)
  • portを9998(readonly)にすると、18秒くらいかかったり? 謎
% time perl test_client.pl
$VAR1 = 0;
perl test_client.pl  1.47s user 2.23s system 41% cpu 8.854 total