Super-Smack solaris10 x86_32bit インストール

MySQLを含め、PostgreSQLOracleで使えるDB負荷テストツール、Super Smackをインストールしてみる。
配布サイト→http://vegan.net/tony/supersmack/さんのところの Solaris10 x86 バイナリがバージョンが古いので1.3をsourceからコンパイル

MySQL 32bit版のパッケージなどを/usr/local/mysqlに展開

正確に測定するためSuperSmackとMySQLは違うホストに入れます。
ただ、Super-SmackにはMySQLクライアントライブラリが必要なので、手っ取り早くTAR PACKAGE版でも展開しましょう。

今回は、以下の構成を用意。

  • Super Smackホスト 192.168.1.101 ※MySQL 5.1.23 32bit版
  • MySQLサーバホスト 192.168.1.102 ※MySQL 5.1.23 64bit版
細かい注意
  • bison2.xxを使う
    • なんか/usr/sfw/bin以下のbisonを使うとエラーが出ます。
    • 他のutilも新しいほうがいいかも・・・
  • libmysqlclient.soのディレクトリをRUNPATHに
  • LDFLAGSにおまじない"-lsocket -lnsl -lm"
bash-3.00# LDFLAGS="-lsocket -lnsl -lm -R/usr/local/mysql/lib/ -L/usr/local/mysql/lib/ " ./configure --with-mysql
/usr/share/smacks/select-key.smackを参考にsmackファイルを作成

以下の部分を書き換える

 user "root";
 host "192.168.1.102";
 db "test";
 pass "xxxxxxxxxxxxx";
テストデータ作成

Super Smackホスト 192.168.1.101側で作業

bash-3.00# /usr/local/bin/gen-data -n 90000 -f %12-12s%n,%25-25s,%n,%d > /var/tmp/words.dat
bash-3.00# scp /var/tmp/words.dat 192.168.1.102:/var/tmp/
DBサーバ側にテーブルを作る

MySQLサーバホスト 192.168.1.102側で作業

create table http_auth
   (username char(25) not null primary key,
    pass char(25),
    uid integer not null,
    gid integer not null
   )";
データのロード

DBサーバ側でデータをテーブルに取り込む

mysql> LOAD DATA INFILE '/tmp/words.dat' INTO TABLE test.http_auth FIELDS TERMINATED BY ',';
smack!

super-smack <設定ファイル> <同時接続数> <トランザクション数>
※5.1系の上限スレッド数は150がデフォルト

bash-3.00# /usr/local/bin/super-smack /usr/share/smacks/select-key_mosa.smack 150 100
Query Barrel Report for client smacker1
connect: max=45ms  min=1ms avg= 9ms from 150 clients
Query_type      num_queries     max_time        min_time        q_per_s
select_index    30000   53      0       22479.87

レプリケーションが"LOAD DATA INFILE"後に再開できない件

Super-Smackをインストール後にレプリケーションが再開できないことに気がついた orz
負荷試験などの前にはレプリケーションをSTOP/STARTすることは良くあると思いますが、今回も試験前に[stop slave]でレプリケーションを止めていたのですが、以下のエラーが出てレプリケーションが再開できません。

bash3.0 # less /usr/local/mysql_64/data/slave.err
〜色々と略〜
080411 15:17:06 [ERROR] Error reading packet from server: error reading log entry ( server_errno=1236)
080411 15:17:06 [ERROR] Got fatal error 1236: 'error reading log entry' from master when reading data fr
om binary log

どうやら"max_allowed_packet"の制限に引っかかっている模様。
MySQLのバージョンはmaster、slaveとも5.1.23・・・binlog_formatがMIXEDなせいの問題かな?あとで検証してみよう。※検証した。STATEMENTでも発生。

とりあえず回避方法は以下。

slave > stop slave;
master> set global max_allowed_packet = 10484736; ←LOADした量に応じてサイズは変える
slave > set global max_allowed_packet = 10484736; 
slave > start slave;


my.cnfに max_allowed_packet を指定してもいいが、上記の方法なら再起動が要りません。デフォルトは1MBなので、不必要なら元に戻しておきましょう。

レプリケーションの遅延を計るシンプルな方法

MySQLレプリケーションをするときに、必ず気になるのが master-slave間の遅延だと思います。
そこで、先日のDeNAさんのテクノロジーセミナーで開示していただいたネタをもとに簡単な遅延監視方法を実装してみました。

  • MySQLバージョン 5.1.23
    • binlog_format=MIXED


まずmasterに以下のようなテーブルを作ります。databaseは適当に作ってください。

CREATE TABLE `replitimes` (
  `No` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `ldate` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`No`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

当然slaveにも同じものが作成されたと思います。作成されてない人は遅延監視とか以前の問題ですね^^;


次に、master側で以下のようなSQLを実行してみましょう。

master> INSERT INTO replitimes (ldate) value (sysdate());


次にslaveで以下のようなクエリを投げて見ましょう。

slave > select * from replitimes;
+----+---------------------+---------------------+
| No | date                | ldate               |
+----+---------------------+---------------------+
|  1 | 2008-04-11 17:57:12 | 2008-04-11 17:57:12 |
+----+---------------------+---------------------+
1 row in set (0.00 sec)

きちんと反映されたでしょうか?
さて、それでは遅延をわざと発生させてどう変化するか確かめてみましょう。

slave > stop slave;
master> INSERT INTO replitimes (ldate) value (sysdate());
〜数秒待ってください〜
slave > start slave;
mysql> select *,ldate - date as delay from replitimes;
+----+---------------------+---------------------+-------+
| No | date                | ldate               | delay |
+----+---------------------+---------------------+-------+
|  1 | 2008-04-11 17:57:12 | 2008-04-11 17:57:12 |     0 |
|  2 | 2008-04-11 18:02:15 | 2008-04-11 18:02:24 |     9 |
+----+---------------------+---------------------+-------+
2 rows in set (0.00 sec)

[date]にはmasterでnow()を実行したときと同じTIMESTAMP値が、[ldate]にはslaveでsysdate()が実行されたときの時間が記録されたかと思います。


sysdate()を使うのがコツです。理由はbinlogを眺めてもらえれば自明ですね。

bash3.0 # ./bin/mysqlbinlog /usr/local/mysql_64/data/mysql-bin.000018
〜色々と中略〜
# at 4988971
#080411 18:02:15 server id 1  end_log_pos 4989094       Query   thread_id=1     exec_time=0     error_code=0
SET TIMESTAMP=1207904535/*!*/;
INSERT INTO replitimes (ldate) value (sysdate())/*!*/;
DELIMITER ;
# End of log file


ここで一つ注意なのが、パラメータ[binlog_format]です。
5.1.23では、以下の3つが選べます。

  • MIXED(Default)
  • STATEMENT
  • ROW

これを ROW にして行ベースレプリケーション(RBR)にしてしまうと、今回の手法は使えません。
MySQL5.1.12以降では、標準で MIXED が設定されているので敢えて変えない限りはこの手法で遅延を検出できます。(STATEMENTでも同じ動作を得ることが可能です)。詳細は・・・まあマニュアルを読んでください。
5.0系はいまのところステートメントベースレプリケーション(SBR)であり、5.1系で言うところの STATEMENT と同じ状況なので、この手法が使えると思います。