MyNA会でdimSTATについて話してきました

お題の通り話してきました。
@kamipoさんOracle Ace認定おめでとうございますの会でした。

ハッシュタグ(#mysql_jp)見てると自分の話は誰得だったのか良く分からんなぁと。
こんなツールがあってこんなこと見れるんだよ、というのを知ってもらえたのなら十分かと思います。

dimSTATのインストール方法とかは以前のはてダに書いてあるので興味をもたれた方は参考にしてもらえると幸いです。

スライドの補足

5.7.8でパラメータの挙動の違いについて見てみた、の環境はLinkbenchのスコアから推測出切るとは思いますがxfs使っています。
本当はもうちょっと突き詰めたかったんですが時間が足りませんでした。

またデモの時に流したLinkbenchは
innodb_io_capacity = 55000
innodb_io_capacity_max = 60000
でどうなるか試した内容でした。結果のスコアは34905なのでやはり上げすぎない方が性能は出るようです。

その際にgeneral_log有効にしてもあまり遅くならなかったよ、と
話した部分がありますが、それはあくまでもバッファプールに
データが乗り切らなくなり、データに満遍なくアクセスがある
ケースです(ioが頻繁に発生する状況)。

データ・INDEXがバッファプールに全部載っている状態、または
アクセスされるデータに局所性がある場合はgeneral_logの待ちにより
全く性能がスケールしなくなります。
この辺についてはMySQL calualのSlackチャンネルの過去ログを見て
頂ければと思います。

innodb_monitor, performance_schemaの細かい部分はドキュメントもなく、
意味するところはソースのコメント見ないといけなかったりするのが
まだ残念な状態です。項目名から意味を類推しつつソース覗いてみて、
あとはベンチマーク実行して挙動をみてみる感じになっています。
※ソースをがっつり読める人はもうちょっと楽だと思います。

ext4の方がどうして遅いのかな、とfio + perf + Flame Graphsで載せましたが、
MySQL + perf + Flame Graphsじゃないのはベンチマーク中にperfをMySQLに対して
実行すると8割以上Kernel panicやら何も出力なく固まるやらしたためでした。
運良く取れたのもあるんですが、これが原因、というのが見やすい感じじゃ
なかったので載せてません。

writeonlyだとext4が遅いですが、readの場合はmutex_lock取らないので
readonlyならfioで計測されるiopsはext4もxfsとほぼ同じになります。
readwriteだと当然xfsが優勢です。



会場提供のGMOさん、主催のyoku0825さん、ありがとうございました。

dimSTATのインストール

MySQLに関するブログを書かれている(というか中の人?)Dimitriさん作成のdimSTATのインストール手順についてまとめます。確認した環境は全てCentOS6(64bit)です。
URLはこちら(Dimitri (dim) Tools HOMEPAGE)。
Dimitriさんのブログはこちら(DimitriK's (dim) Weblog)

dimSTATはDimitriさんのブログに登場するグラフを生成してくれるリソースモニタです。
Performance Schemaのデータも割りと簡単にグラフ化出来るので性能測定の際には非常に便利なツールとなっています。

事前準備

compressコマンドのインストールとアカウント作成

インストール時にcompressコマンドが入っているかチェックされ、入っていない場合はパッケージに含まれるcompressコマンドがインストールされるようでしたので予めyumでインストールしておきます。

また、dim_STAT用のアカウントであるdimを作成しておきます。変更は可能ですので、違うアカウント名にしたい場合はインストール時に変更して下さい。

$ sudo yum install ncompress
$ sudo useradd -s /bin/bash -d /home/dim dim
$ sudo passwd dim

32bitな以下も必要なのでインストールされていない場合はインストール。32bit環境の場合は既に入っているかもしれません。

$ sudo yum install zlib.i686 libgcc.i686 libstdc++.i686 libX11.i686 ncurses-libs.i686

インストール後に何か上手く動いてないようでしたら/apps/httpd/etc/logs/error_logを見ると足りないライブラリが書かれていたりするの適宜追加しましょう。

出力例
/apps/mysql/bin/mysql: error while loading shared libraries: libncurses.so.5: cannot open shared object file: No such file or directory
どのパッケージに含まれるか調べる場合は以下のように。
$ sudo yum whatprovides */libncurses.so.5

dim_STATのインストール

dim_STATのダウンロードと展開
$ wget 'http://dimitrik.free.fr/dim_STAT-v90-linux-x86.tar'
$ tar xf dim_STAT-v90-linux-x86.tar
インストールの実行と起動

INSTALL.shでインストールを行います。以下の例ではHTTPのポート番号のみ8080へ変更しています。

$ cd dim_STAT-INSTALL
$ sudo ./INSTALL.sh
compress: ok


===========================================
** Starting dim_STAT Server INSTALLATION **
===========================================

HOSTNAME: [ホスト名]
      IP: [IPアドレス]
 DOMAINE: (none)

Is it correct? (y/n): y
**
** ATTENTION!
**
** On your host You have to assign a USER/GROUP pair as owner
** of all dim_STAT modules (default: dim/dim)

 User: dim
Group: dim

Is it correct? (y/n): y


**
** WARNING!!!
**
** On your host You have already created USER: dim
** This user will be the owner of all
** dim_STAT modules...
**
== /etc/passwd: =========================================================

dim:x:10002:10002::/home/dim:/bin/bash

=========================================================================

Is it correct? (y/n): y


======================================
** dim_STAT Directory Configuration **
======================================

** WebX root directory (5MB):
 => /WebX
 => /apps/WebX
 => /opt/WebX
 => /etc/WebX

 [/opt/WebX]:


** HOME directory for dim_STAT pkgs        [/apps]:
** TEMP directory                          [/tmp]:

** HTTP Server Port                        [80]: 8080
** DataBase Server Port                    [3306]:
** Default STAT-service Port               [5000]:


==================================================
** Process...
==================================================
=> Host                        : [ホスト名]
=> IP address                  : [IPアドレス]
=> Domain                      : (none)
=> User                        : dim
=> Group                       : dim
=> WebX root directory         : /opt/WebX
=> HOME directory              : /apps
=> TEMP directory              : /tmp
=> HTTP Server Port            : 8080
=> DataBase Server Port        : 3306
=> Default STAT-service Port   : 5000

Is it correct? (y/n): y


** !!
** !! !!! WARNING !!!
** !! ---------------
** !!
** !! ALL DATA will be DELETED!!! in: /apps/* !!!
** !! as well /WebX, /apps/WebX, /etc/WebX, /opt/WebX !!!
** !!
Delete all data? (y/n): y




** Cleanup /apps
** WebX Setup...
** dim_STAT Server extract...
** HTTP Server Setup...
** Database Server Setup...
** ADMIN/Tools Setup...
** TEMP directory...
** Permissions...
** Crontab Setup...


**
** INSTALLATION is finished!!!
**
May I create now a dim_STAT-Server start/stop script in /etc/rc*.d? (y/n): y
ln: creating symbolic link `/etc/rcS.d/K99dimstat' to `/apps/ADMIN/dim_STAT-Server': No such file or directory
============================================================================
 NOTE:
 =>
 => Please, set a password to the user dim
 => to enable crontab "clean up" procedure!..
 =>


** =========================================================================
**
**   You can start dim_STAT-Server now from /apps/ADMIN:
**
**   # cd /apps/ADMIN
**   # ./dim_STAT-Server start
**
**   and access homepage via Web browser - http://4a-p01-b5:8080
**
**   To collect stats from any Solaris, Linux or MacOSX machines just
**   install & start on them a correcponding [STAT-service] package...
**
** Enjoy! ;-)
**
** -Dimitri
** =========================================================================


$
$ ls -dl /etc/rc?.d/*dimstat
lrwxrwxrwx 1 root root 27 May 23 09:02 /etc/rc0.d/K99dimstat -> /apps/ADMIN/dim_STAT-Server
lrwxrwxrwx 1 root root 27 May 23 09:02 /etc/rc1.d/K99dimstat -> /apps/ADMIN/dim_STAT-Server
lrwxrwxrwx 1 root root 27 May 23 09:02 /etc/rc2.d/S99dimstat -> /apps/ADMIN/dim_STAT-Server
$
$ /etc/rc2.d/S99dimstat start
================[ dim_STAT-Server: start ]================

*
* MySQL Database Server
*
  => Log output  : /apps/mysql/data/mysqld.log
  => Local socket: /apps/mysql/data/mysql.sock
  => Admin Access: root# /apps/mysql/bin/mysql -S /apps/mysql/data/mysql.sock

Starting...
150523 09:07:36 mysqld_safe Logging to '/apps/mysql/data/mysqld.log'.
150523 09:07:36 mysqld_safe Starting mysqld daemon with databases from /apps/mysql/data
Done.
Starting HTTP server from: /apps/httpd
Done.
================[ dim_STAT-Server: start -- done. ]================
$

アップデートファイルの適用(2015/08/08追加)

ここまでの作業でCoreとなるパッケージはインストールが完了しました。続いてアップデートファイルを適用します。
ダウンロードファイル一覧

$ cd /opt/WebX/
$ wget 'http://dimitrik.free.fr/Core_Updates/WebX_apps-v90-u14.tgz'
$ tar zxf WebX_apps-v90-u14.tgz

以上でアップデートファイルの適用は完了です。

STAT-service

dim_STATでリソース取得を行う場合、取得対象となる全てのサーバでSTAT-serviceを起動する必要があります。

STAT-serviceのダウンロード、インストールと設定

MySQLのアドオンも含まれてるSTATsrvをインストールします。

$ wget http://dimitrik.free.fr/STATsrv-Linux-x86-mysql.tgz
$ tar zxf STATsrv-Linux-x86-mysql.tgz
$ sudo mv -i STATsrv /etc/.

MySQLのリソースも取得したい場合は取得したいサーバで以下の設定を行います。

$ cd /etc/STATsrv/bin
$ sudo cp -pi .env-mysql .env-mysql.ORG
$ sudo vi .env-mysql
$ cat .env-mysql
# Set connection params:
User=[ユーザ名]
Passwd=[パスワード]
Host=[IPアドレス]:[ポート番号]

export User Passwd Host

$

.env-mysqlの設定例としては以下のようになります。

# Set connection params:
User=dim
Passwd=dim-pw
Host=192.168.1.100:3306

export User Passwd Host

リソース取得を行いたいMySQLで.env-mysqlで設定したアカウントを作成しておきます。
権限はなんとなくPercona Templateと合わせています。見てる感じ足りてそうですが不足してそうなら足して下さい。

GRANT SUPER,PROCESS ON *.* to dim@'192.168.1.0/255.255.255.0' IDENTIFIED BY 'dim-pw';

リソース取得を行いたい各サーバでプロセスを起動し、準備完了です。

$ cd /etc/STATsrv/
$ sudo ./STAT-service start
Start STAT-service...
   port: 5000
   access log: /etc/STATsrv/log/access.log
$

簡単な初期設定例

dimSTATをインストールしたマシンのIPアドレスを指定する形で http://[インストールIPアドレス]:8080 でアクセスすると以下画面が表示されます。

まずはWelcome!をクリックして以下の画面へ移動します。

先にリソースを取得するサーバを追加する前にアドオンを追加しておきます。

画面下部にMySQL関連のものが3つあるので全部追加します。

終わったら画面右上の[Home]をクリックしてTOPに戻り、モニタするサーバを追加します。[Start New Collect]をクリックします。
NewにIPアドレスなりホスト名を入力して[Continue...]をクリックします。

取得したい対象をチェックし、[Start STAT(S) Collect NOW!!!]をクリックしてモニタリングを開始します。

再び[Home]をクリックしてTOPに戻り、[Analyze]をクリックします。
以下画面になるので特に弄らないで[Analyze]をクリック。

追加したサーバを選択して、分かりやすいのでまずは[Bookmark(s)]をクリックします。

以下画面が表示されるのでとりあえず[InnoDB_HistLen]をクリックします。

すると以下のようにグラフが表示されます。MySQL起動後何もしていないのでグラフはまっすぐです。

割とちゃんと描画しているサンプルは以下のようになります。

おわりに

細かい解説すると切りが無いのですが、とりあえず使うのであれば以上で十分かと思います。
my.cnfに記載するPerformance Schemaの設定は以下で良いかと思います。

performance_schema = ON
performance_schema_instrument='%sync%=on'

dimSTATで起動するApacheがかなり古いので、iptables等で適切にアクセス制御を行う、または127.0.0.1にバインドして起動させ、nginxとかでProxyさせた方が良いと思います。完全にプライベートな環境であればそこまで神経質にならなくても良いかもしれませんが、不特定多数からアクセスされる可能性のあるサーバの場合は気をつけた方が良さそうです。

個人的にはPerformance Schema関連をお手軽にグラフに出来るのでLinkBenchと合わせて使い始めています。ガチサービス中のマシンでは使ってないのでもし使う場合は十分に確認の上、ご利用下さい。

LinkBenchのインストールと使用について

気づいたら1年以上書いてなかった。。。

最近は色々なPCI-E SSDベンチマークを取る機会が多くなっていて、tpcc-mysqlだと負荷不足な感じなのと、異なる傾向のI/O負荷の高いベンチマークを取ってみたかったので以前から気になっていたFacebook製のLinkBenchを使い始めています(LinkBenchのgithub)。
今回はベンチマーククライアントに使っているOSがCentOS5系だったのでCentOS5系でのインストール方法について記載します。基本的にはCentOS6系でも変わらないと思います。

またgithubに書かれている内容を元に、実際にやってみた内容をまとめています。

事前準備

Javamavenインストール及び設定

この辺はお好みでインストール場所とかは変更して下さい。
Javaは7以上が必要なようなのでCentOS5系ではyumからインストールしています。

$ sudo yum install java-1.7.0-openjdk java-1.7.0-openjdk-devel
$ wget http://ftp.riken.jp/net/apache/maven/maven-3/3.3.3/binaries/apache-maven-3.3.3-bin.tar.gz
$ tar zxf apache-maven-3.3.3-bin.tar.gz
$ sudo mv -i apache-maven-3.3.3 /usr/local/.
JAVA_HOMEの設定とmavenへのPATH登録

LinkBenchのインストールの際に必要になるので以下のように環境変数を設定してください。適宜.bash_profileとかに書いておく事が推奨です。

$ export JAVA_HOME=/usr/lib/jvm/jre-1.7.0-openjdk.x86_64
$ export PATH=/usr/local/apache-maven-3.3.3/bin:$PATH

LinkBenchのインストール

例によってgitコマンドで取得してmvnコマンドでインストール(ビルド?)します。すみませんがmavenよく知りません。。。

$ git clone https://github.com/facebook/linkbench.git
$ cd linkbench
$ mvn clean package

試してないですが、テストを限定する場合

$ mvn clean package -P fast-test

テストをスキップする場合

$ mvn clean package -DskipTests

とするようです。

以下が出ればインストール成功みたいです。

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 07:29 min
[INFO] Finished at: 2015-05-13T01:59:05+09:00
[INFO] Final Memory: 80M/1758M
[INFO] ------------------------------------------------------------------------
実行確認
$ ./bin/linkbench
Using java at: /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/java
Did not select benchmark mode
usage: linkbench [-c <file>] [-csvstats <file>] [-csvstream <file>] [-D
       <property=value>] [-L <file>] [-l] [-r]
 -c <file>                       Linkbench config file
 -csvstats,--csvstats <file>     CSV stats output
 -csvstream,--csvstream <file>   CSV streaming stats output
 -D <property=value>             Override a config setting
 -L <file>                       Log to this file
 -l                              Execute loading stage of benchmark
 -r                              Execute request stage of benchmark
$

MySQLの準備

ベンチマークを行うハードウェアで動作するMySQLで以下のようにデータベース作成等、準備を行います。まずは以下を実行します。

create database linkdb;
use linkdb;

CREATE TABLE `linktable` (
  `id1` bigint(20) unsigned NOT NULL DEFAULT '0',
  `id2` bigint(20) unsigned NOT NULL DEFAULT '0',
  `link_type` bigint(20) unsigned NOT NULL DEFAULT '0',
  `visibility` tinyint(3) NOT NULL DEFAULT '0',
  `data` varchar(255) NOT NULL DEFAULT '',
  `time` bigint(20) unsigned NOT NULL DEFAULT '0',
  `version` int(11) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (link_type, `id1`,`id2`),
  KEY `id1_type` (`id1`,`link_type`,`visibility`,`time`,`id2`,`version`,`data`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 PARTITION BY key(id1) PARTITIONS 16;

CREATE TABLE `counttable` (
  `id` bigint(20) unsigned NOT NULL DEFAULT '0',
  `link_type` bigint(20) unsigned NOT NULL DEFAULT '0',
  `count` int(10) unsigned NOT NULL DEFAULT '0',
  `time` bigint(20) unsigned NOT NULL DEFAULT '0',
  `version` bigint(20) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`,`link_type`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `nodetable` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `type` int(10) unsigned NOT NULL,
  `version` bigint(20) unsigned NOT NULL,
  `time` int(10) unsigned NOT NULL,
  `data` mediumtext NOT NULL,
  PRIMARY KEY(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

続いてベンチマーク用のMySQLアカウントを作成します。リモートからベンチマークを実行する場合は適宜localhostを192.168.1.0/255.255.255.0とかに変更して下さい。

CREATE USER 'linkbench'@'localhost' IDENTIFIED BY 'パスワード';
GRANT ALL ON linkdb.* TO 'linkbench'@'localhost';

最小限の設定

config/FBWorkload.propertiesファイルで最小限の設定(接続情報)を記載します 。その他、負荷に関する設定も記述されています。
またconfig/FBWorkload.propertiesにはデータ量に関する設定も記述されています。

$ cp config/LinkConfigMysql.properties config/MyConfig.properties
$ vi config/MyConfig.properties
$ diff -U3 config/LinkConfigMysql.properties config/MyConfig.properties
--- config/LinkConfigMysql.properties   2015-05-13 01:42:23.000000000 +0900
+++ config/MyConfig.properties  2015-05-13 05:17:50.000000000 +0900
@@ -27,9 +27,9 @@
 nodestore = com.facebook.LinkBench.LinkStoreMysql

 # MySQL connection information
-host = yourhostname.here
-user = MySQLuser
-password = MySQLpass
+host = [IPアドレスorホストネーム]
+user = linkbench
+password = [パスワード]
 port = 3306
 # dbid: the database name to use
 dbid = linkdb
$

ベンチマーク用データのロード

以下コマンドでベンチマーク用のデータをロードします。
innodb_page_size=4kの場合、約12GBのデータが作成されます。

$ ./bin/linkbench -c config/MyConfig.properties -l

事前にMySQLに接続して以下を実行する事でロード時間の短縮が行えます。

use linkdb;
alter table linktable drop key `id1_type`;
set global innodb_flush_log_at_trx_commit = 2;
set global sync_binlog = 0;

ロードが終わったら以下コマンドを実行して環境を元に戻すのを忘れないで下さい。

set global innodb_flush_log_at_trx_commit = 1;
set global sync_binlog = 1;
alter table linktable add key `id1_type`
  (`id1`,`link_type`,`visibility`,`time`,`id2`,`version`,`data`);

INDEXも貼り直した状態で以下のファイルサイズで作成されました。

$ ls -lh /var/lib/mysql/linkdb/
total 12G
-rw-rw---- 1 mysql mysql 8.5K May 13 05:12 counttable.frm
-rw-rw---- 1 mysql mysql 584M May 13 05:30 counttable.ibd
-rw-rw---- 1 mysql mysql   61 May 13 05:12 db.opt
-rw-rw---- 1 mysql mysql 8.6K May 13 05:33 linktable.frm
-rw-rw---- 1 mysql mysql   88 May 13 05:33 linktable.par
-rw-rw---- 1 mysql mysql 400M May 13 05:33 linktable#P#p0.ibd
-rw-rw---- 1 mysql mysql 548M May 13 05:35 linktable#P#p10.ibd
-rw-rw---- 1 mysql mysql 300M May 13 05:35 linktable#P#p11.ibd
-rw-rw---- 1 mysql mysql 440M May 13 05:35 linktable#P#p12.ibd
-rw-rw---- 1 mysql mysql 364M May 13 05:35 linktable#P#p13.ibd
-rw-rw---- 1 mysql mysql 668M May 13 05:35 linktable#P#p14.ibd
-rw-rw---- 1 mysql mysql 376M May 13 05:36 linktable#P#p15.ibd
-rw-rw---- 1 mysql mysql 380M May 13 05:33 linktable#P#p1.ibd
-rw-rw---- 1 mysql mysql 676M May 13 05:33 linktable#P#p2.ibd
-rw-rw---- 1 mysql mysql 324M May 13 05:33 linktable#P#p3.ibd
-rw-rw---- 1 mysql mysql 416M May 13 05:33 linktable#P#p4.ibd
-rw-rw---- 1 mysql mysql 296M May 13 05:34 linktable#P#p5.ibd
-rw-rw---- 1 mysql mysql 832M May 13 05:34 linktable#P#p6.ibd
-rw-rw---- 1 mysql mysql 344M May 13 05:34 linktable#P#p7.ibd
-rw-rw---- 1 mysql mysql 432M May 13 05:34 linktable#P#p8.ibd
-rw-rw---- 1 mysql mysql 352M May 13 05:34 linktable#P#p9.ibd
-rw-rw---- 1 mysql mysql 8.5K May 13 05:26 nodetable.frm
-rw-rw---- 1 mysql mysql 3.6G May 13 05:31 nodetable.ibd
$

config/FBWorkload.properties の maxid1 = 200000001 にすると218GBのデータが作成されました。

$ du -sch /var/lib/mysql/linkdb/
218G    /var/lib/mysql/linkdb/
218G    total
$
$ ls -lh /var/lib/mysql/linkdb/
total 218G
-rw-rw---- 1 mysql mysql 8.5K May 13 05:43 counttable.frm
-rw-rw---- 1 mysql mysql  12G May 13 06:20 counttable.ibd
-rw-rw---- 1 mysql mysql   61 May 13 05:43 db.opt
-rw-rw---- 1 mysql mysql 8.6K May 13 16:35 linktable.frm
-rw-rw---- 1 mysql mysql   88 May 13 16:35 linktable.par
-rw-rw---- 1 mysql mysql 6.6G May 13 16:43 linktable#P#p0.ibd
-rw-rw---- 1 mysql mysql 6.0G May 13 18:17 linktable#P#p10.ibd
-rw-rw---- 1 mysql mysql  12G May 13 18:31 linktable#P#p11.ibd
-rw-rw---- 1 mysql mysql 5.4G May 13 18:37 linktable#P#p12.ibd
-rw-rw---- 1 mysql mysql 9.4G May 13 18:48 linktable#P#p13.ibd
-rw-rw---- 1 mysql mysql 5.9G May 13 18:54 linktable#P#p14.ibd
-rw-rw---- 1 mysql mysql  14G May 13 19:11 linktable#P#p15.ibd
-rw-rw---- 1 mysql mysql 6.0G May 13 16:50 linktable#P#p1.ibd
-rw-rw---- 1 mysql mysql 5.7G May 13 16:56 linktable#P#p2.ibd
-rw-rw---- 1 mysql mysql  18G May 13 17:17 linktable#P#p3.ibd
-rw-rw---- 1 mysql mysql 5.6G May 13 17:23 linktable#P#p4.ibd
-rw-rw---- 1 mysql mysql 9.9G May 13 17:34 linktable#P#p5.ibd
-rw-rw---- 1 mysql mysql 5.7G May 13 17:40 linktable#P#p6.ibd
-rw-rw---- 1 mysql mysql  13G May 13 17:55 linktable#P#p7.ibd
-rw-rw---- 1 mysql mysql 6.4G May 13 18:02 linktable#P#p8.ibd
-rw-rw---- 1 mysql mysql 8.0G May 13 18:11 linktable#P#p9.ibd
-rw-rw---- 1 mysql mysql 8.5K May 13 05:44 nodetable.frm
-rw-rw---- 1 mysql mysql  71G May 13 07:31 nodetable.ibd
$

LinkBenchの実行

以下コマンドでベンチマークを実行します。デフォルトでは200接続で負荷を掛ける事になります(requesters = 100だけど接続数は200のようでした)。
config/MyConfig.propertiesの requesters = 100 を編集する事で接続数は変更可能です。実行時にオプションとして渡す事も出来ます。

$ ./bin/linkbench -c config/MyConfig.properties -r

requestersを50として実行する場合は以下のようになります。

$ ./bin/linkbench -c config/MyConfig.properties -D requesters=50 -r

また、10分間のwarmupを行う場合は以下のようになります。設定ファイルではwarmup_time = 0でデフォルト0秒です。

$ ./bin/linkbench -c config/MyConfig.properties -D warmup_time=600 -r

スレッド毎にもレポートは出ますが、サマリーとしては以下のような出力になります。それぞれのレイテンシーについての出力もあります(時間は削除しています)。

[main]: ADD_NODE count = 1286123  p25 = [2,3]ms  p50 = [4,5]ms  p75 = [8,9]ms  p95 = [25,26]ms  p99 = [47,48]ms  max = 350.06ms  mean = 7.336ms
[main]: UPDATE_NODE count = 3680962  p25 = [2,3]ms  p50 = [4,5]ms  p75 = [9,10]ms  p95 = [27,28]ms  p99 = [48,49]ms  max = 419.252ms  mean = 8.255ms
[main]: DELETE_NODE count = 505534  p25 = [2,3]ms  p50 = [4,5]ms  p75 = [8,9]ms  p95 = [25,26]ms  p99 = [46,47]ms  max = 360.033ms  mean = 7.705ms
[main]: GET_NODE count = 6468958  p25 = [0.4,0.5]ms  p50 = [1,2]ms  p75 = [3,4]ms  p95 = [10,11]ms  p99 = [18,19]ms  max = 143.47ms  mean = 2.753ms
[main]: ADD_LINK count = 4493508  p25 = [4,5]ms  p50 = [7,8]ms  p75 = [20,21]ms  p95 = [55,56]ms  p99 = [90,91]ms  max = 896.368ms  mean = 15.965ms
[main]: DELETE_LINK count = 1495732  p25 = [0.5,0.6]ms  p50 = [1,2]ms  p75 = [6,7]ms  p95 = [39,40]ms  p99 = [79,80]ms  max = 609.526ms  mean = 7.77ms
[main]: UPDATE_LINK count = 4004540  p25 = [4,5]ms  p50 = [7,8]ms  p75 = [20,21]ms  p95 = [53,54]ms  p99 = [89,90]ms  max = 902.957ms  mean = 15.641ms
[main]: COUNT_LINK count = 2440215  p25 = [0.2,0.3]ms  p50 = [0.4,0.5]ms  p75 = [1,2]ms  p95 = [6,7]ms  p99 = [13,14]ms  max = 113.011ms  mean = 1.335ms
[main]: MULTIGET_LINK count = 263447  p25 = [0.2,0.3]ms  p50 = [0.3,0.4]ms  p75 = [0.7,0.8]ms  p95 = [4,5]ms  p99 = [12,13]ms  max = 442.304ms  mean = 1.144ms
[main]: GET_LINKS_LIST count = 25360981  p25 = [0.2,0.3]ms  p50 = [0.4,0.5]ms  p75 = [0.7,0.8]ms  p95 = [4,5]ms  p99 = [13,14]ms  max = 2795.329ms  mean = 1.21ms
[main]: REQUEST PHASE COMPLETED. 50000000 requests done in 2461 seconds. Requests/second = 20311

ベンチマーク後のファイルサイズは以下のようになりました。

$ du -sch /var/lib/mysql/linkdb/
246G    /var/lib/mysql/linkdb/
$
$ ls -lh /var/lib/mysql/linkdb/
total 246G
-rw-rw---- 1 mysql mysql 8.5K May 13 05:43 counttable.frm
-rw-rw---- 1 mysql mysql  13G May 14 03:36 counttable.ibd
-rw-rw---- 1 mysql mysql   61 May 13 05:43 db.opt
-rw-rw---- 1 mysql mysql 8.6K May 13 16:35 linktable.frm
-rw-rw---- 1 mysql mysql   88 May 13 16:35 linktable.par
-rw-rw---- 1 mysql mysql 7.7G May 14 03:36 linktable#P#p0.ibd
-rw-rw---- 1 mysql mysql 7.1G May 14 03:36 linktable#P#p10.ibd
-rw-rw---- 1 mysql mysql  14G May 14 03:36 linktable#P#p11.ibd
-rw-rw---- 1 mysql mysql 6.4G May 14 03:36 linktable#P#p12.ibd
-rw-rw---- 1 mysql mysql  12G May 14 03:36 linktable#P#p13.ibd
-rw-rw---- 1 mysql mysql 7.0G May 14 03:36 linktable#P#p14.ibd
-rw-rw---- 1 mysql mysql  16G May 14 03:36 linktable#P#p15.ibd
-rw-rw---- 1 mysql mysql 7.0G May 14 03:36 linktable#P#p1.ibd
-rw-rw---- 1 mysql mysql 6.8G May 14 03:36 linktable#P#p2.ibd
-rw-rw---- 1 mysql mysql  21G May 14 03:36 linktable#P#p3.ibd
-rw-rw---- 1 mysql mysql 6.7G May 14 03:36 linktable#P#p4.ibd
-rw-rw---- 1 mysql mysql  12G May 14 03:36 linktable#P#p5.ibd
-rw-rw---- 1 mysql mysql 6.8G May 14 03:36 linktable#P#p6.ibd
-rw-rw---- 1 mysql mysql  16G May 14 03:36 linktable#P#p7.ibd
-rw-rw---- 1 mysql mysql 7.5G May 14 03:36 linktable#P#p8.ibd
-rw-rw---- 1 mysql mysql 9.5G May 14 03:36 linktable#P#p9.ibd
-rw-rw---- 1 mysql mysql 8.5K May 13 05:44 nodetable.frm
-rw-rw---- 1 mysql mysql  73G May 14 03:36 nodetable.ibd
$

終わりに

その他色々細かい設定もあるみたいです。今の所はほぼ初期の設定で使用していますがデフォルトのrequesters = 100だと相当の負荷がかかります。HDDでは5とかに減らす事をお勧めします(SATAのHDDとか100で負荷かけたらすぐ壊れそう)。感覚的にはSSDなら32ぐらいから試すと良いと思います。

ベンチマークの結果は所詮目安ですが、チューニングの勉強にもなるので色々やってみると面白いですよ。

performance_schemaによる秒間接続数の性能差

前回はperformance_schema(以下p_s)の無効、有効、有効でsetup_instrumentsテーブルのENABLED列を全てNOにした場合の性能測定を行いました。こちらは結果としてsetup_instrumentsテーブルのENABLED列を全てNOにするとp_sをOFFにした場合とあまり性能が変わらない所まで改善する事が確認出来ました。

p_sが有効にすると性能が下がるというのは松信さんのブログでも書かれているのでご存知の方も多いかと思います。今回はsetup_instrumentsテーブルの設定のより秒間接続数に差が出るか確認を行いました。

ベンチマーク環境は基本前回と同じです。但し、リモートからTCPにより接続する一般的なWEB・DBサーバの環境となるようにしています。今回はNICの情報等も追記しました。

今回も同様に設定ファイルのperformance_schema=ON/OFFを切り替えてテストしています。sysbenchのバージョンは松信さんが実行しているであろうものと同じ0.4.12を使用し、オプションも基本同じ設定としています。oltp-table-sizeのみ変更していますがoltp-dist-type=specialなのであまり意味は無いかもしれません。

ベンチマークのオプション

今回は1パターンしか行っていないので以下内容を設定変更後、MySQLを再起動し、特にバッファに載せる処理は行わず、即時実行としています。

$ /usr/local/sysbench-0.4.12/bin/sysbench \
  --test=oltp \
  --oltp-table-size=4500000 \
  --max-requests=1000000 \
  --mysql-table-engine=innodb \
  --db-ps-mode=disable \
  --mysql-engine-trx=yes \
  --oltp-read-only \
  --oltp-skip-trx \
  --oltp-dist-type=special \
  --oltp-connect-delay=0 \
  --oltp-reconnect-mode=query \
  --db-driver=mysql \
  --mysql-user=sbtest \
  --mysql-password=パスワード \
  --mysql-db=sbtest \
  --mysql-host=サーバIPアドレス \
  --mysql-port=3306 \
  --num-threads=100 \
  run

ベンチマークパターン

今回は以下4パターンで取得しています。接続数関連なのでthread_cache_size=0にしたパターンも行っています。

  • ケース1: p_s OFF
  • ケース2: p_s OFF(thread_cache_size=0)
  • ケース3: p_s ON (setup_instrumentsテーブルのENABLEDが全てOFF)
  • ケース4: p_s ON (setup_instrumentsテーブルのENABLEDが全てOFF, thread_cache_size=0)

ベンチマーク結果

秒間接続数
ケース1 19428
ケース2 15971
ケース3 16575
ケース4 14718

まとめ

残念ながら秒間接続数はsetup_instrumentsテーブルに関わらず減少することが分かりました。thread_cache_sizeが十分に大きければthread_cache_size=0でp_s OFFよりは速いようです。

上記のスコアはtpsにすると1000〜1300程度になります。使用しているサーバに対してsysbench 0.5でUNIX ドメインソケット経由でかつ接続を維持する場合は5600〜6000tpsぐらい出るのでネットワーク越しだとだいぶ接続の負荷により性能が落ちる事が分かります(persistentは可能なら使うべき)。

TCP経由でリモートから、接続維持(--oltp-reconnect-modeがデフォ)だとどのぐらい出るのか気になる方もいるかもしれませんが、1GbpsのNICだと帯域を先に使い切ってしまい正確な値は分かっていません。帯域を使い切っている状態であっても4000tpsぐらいは出ていたと記憶しています。

秒間で10kを超える接続/切断が行われる環境はそう多くないとは思いますがこういった所まで気を配る必要がある環境であればp_sはOFFにした方が良いでしょう。

おまけ

ベンチマーク中にmpstat -P ALLすると以下のようになります。

サーバ側
03:46:03 AM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest   %idle
03:46:06 AM  all   28.67    0.00    8.97    0.08    0.00    6.19    0.00    0.00   56.09
03:46:06 AM    0   52.20    0.00   13.56    0.00    0.00   19.32    0.00    0.00   14.92
03:46:06 AM    1   52.38    0.00   13.27    0.34    0.00   17.69    0.00    0.00   16.33
03:46:06 AM    2   50.17    0.00   13.22    0.00    0.00   18.98    0.00    0.00   17.63
03:46:06 AM    3   48.79    0.00   14.88    0.00    0.00    0.00    0.00    0.00   36.33
03:46:06 AM    4   51.19    0.00   11.86    0.00    0.00   20.00    0.00    0.00   16.95
03:46:06 AM    5   50.51    0.00   11.95    0.00    0.00   18.43    0.00    0.00   19.11
03:46:06 AM    6   29.11    0.00   12.67    0.00    0.00    0.00    0.00    0.00   58.22
03:46:06 AM    7   23.21    0.00   10.58    0.00    0.00    0.00    0.00    0.00   66.21
03:46:06 AM    8   17.75    0.00    6.48    0.00    0.00    0.00    0.00    0.00   75.77
03:46:06 AM    9   11.74    0.00    4.70    0.00    0.00    0.00    0.00    0.00   83.56
03:46:06 AM   10    7.43    0.00    3.72    0.00    0.00    0.00    0.00    0.00   88.85
03:46:06 AM   11    4.71    0.00    2.69    0.00    0.00    0.00    0.00    0.00   92.59
03:46:06 AM   12   41.55    0.00   12.16    0.34    0.00    0.00    0.00    0.00   45.95
03:46:06 AM   13   37.97    0.00   11.19    0.00    0.00    0.00    0.00    0.00   50.85
03:46:06 AM   14   35.27    0.00    9.59    0.34    0.00    0.00    0.00    0.00   54.79
03:46:06 AM   15   45.08    0.00   10.51    0.34    0.00   18.64    0.00    0.00   25.42
03:46:06 AM   16   50.17    0.00   10.51    0.00    0.00   17.29    0.00    0.00   22.03
03:46:06 AM   17   47.62    0.00   11.22    0.00    0.00   18.71    0.00    0.00   22.45
03:46:06 AM   18   10.51    0.00    8.81    0.00    0.00    0.00    0.00    0.00   80.68
03:46:06 AM   19   11.19    0.00   11.86    0.00    0.00    0.00    0.00    0.00   76.95
03:46:06 AM   20    1.34    0.00    0.67    0.00    0.00    0.00    0.00    0.00   97.99
03:46:06 AM   21    5.32    0.00    4.98    0.00    0.00    0.00    0.00    0.00   89.70
03:46:06 AM   22    4.70    0.00    5.37    0.00    0.00    0.00    0.00    0.00   89.93
03:46:06 AM   23    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00

クライアント側
03:45:57 AM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest   %idle
03:46:00 AM  all   16.18    0.00   31.05    0.04    0.00   20.08    0.00    0.59   32.06
03:46:00 AM    0   13.04    0.00   24.41    0.00    0.00   42.47    0.00    1.00   19.06
03:46:00 AM    1   15.59    0.00   30.17    0.00    0.00   27.46    0.00    0.34   26.44
03:46:00 AM    2   14.63    0.00   28.91    0.00    0.00   26.53    0.00    1.36   28.57
03:46:00 AM    3   16.39    0.00   29.43    0.00    0.00   25.08    0.00    0.00   29.10
03:46:00 AM    4   18.58    0.00   36.49    0.00    0.00    8.78    0.00    0.68   35.47
03:46:00 AM    5   17.73    0.00   35.79    0.00    0.00    7.36    0.00    0.33   38.80
03:46:00 AM    6   17.51    0.00   33.00    0.00    0.00    6.40    0.00    0.67   42.42
03:46:00 AM    7   15.67    0.00   29.67    0.33    0.00   17.00    0.00    0.67   36.67

performance_schemaのsetup_instrumentsテーブルによる性能差

先日のMyNA会(2013年7月)の際に@sheeriさんがperformance_schema(以下p_s)について発表されていた際に取得項目がsetup_instrumentsテーブルで制御出来るようなお話をしていました。

MySQL5.6ではp_sが有効だと性能が1割程度落ちたりするというのは最近では割と良く知られてきている話しだと思います。p_sが有効な状態でsetup_instrumentsテーブルで全部取得しないようにした場合にどの程度の性能差が出るか試してみました。

設定ファイルのmysqldセクションでperformance_schema=ON, OFFを切り替えてテストしました。
また今回はread-onlyなケースしか行っていないのでバイナリログ周りの設定は結構ザルです。

ベンチマークについて

設定を変えつつsysbenchを以下の内容で実行しています。

#!/bin/sh

threads='8 16 32 64 128 256 512 1024'
DIR=ケース名

[ ! -d $DIR ] && mkdir $DIR
cp -pi ./mysql/etc/my.cnf $DIR/.

for thread in $threads; do
  echo "==== $thread ===="
  /usr/local/sysbench/bin/sysbench \
    --test=/usr/local/src/sysbench/sysbench/tests/db/oltp.lua \
    --init-rng=1 \
    --db-driver=mysql \
    --db-ps-mode=disable \
    --oltp-table-size=3750000 \
    --oltp-dist-type=uniform \
    --oltp-read-only=on \
    --oltp-tables-count=12 \
    --mysql-db=sbtest5 \
    --mysql-user=sbtest \
    --mysql-password=パスワード\
    --mysql-socket=/tmp/mysql-5.6.13.sock \
    --max-time=180 \
    --max-requests=0 \
    --num-threads=$thread \
    run | tee $DIR/ro-$thread
    sleep 30
done

ベンチマークパターン

以下3パターンで取得しました。

  • ケース1: p_s OFF
  • ケース2: p_s ON (setup_instrumentsテーブルはデフォルト)
  • ケース3: p_s ON (setup_instrumentsテーブルのENABLEDが全てOFF)
    • UPDATE performance_schema.setup_instruments SET enabled = 'NO'; を実行

ベンチマーク結果

上記スクリプト実行前に512スレッドで1分、ベンチマークを実行し、データ/インデックスをバッファに載せる作業をしています。

それほどケースが多くないのでグラフにはしていません。上記のスクリプトによる一発取りです。また、単位はtpsになります。

スレッド数 8 16 32 64 128 256 512 1024
ケース1 2596.08 4413.11 5721.59 5644.72 5619.35 5600.32 5597.74 5697.52
ケース2 2487.02 4333.26 5363.82 5298.40 5278.34 5258.75 5250.21 5333.69
ケース3 2727.37 4673.24 5751.39 5667.72 5671.37 5621.66 5611.42 5609.69

今回に関してはp_sがONでもsetup_instrumentsテーブルのENABLEDが全てNOだとp_sがOFFより性能出てますが所詮一発取りなので誤差と考えられます。とはいえ、p_sがONでも誤差程度の差になったのが割と驚きでした。

ではp_sがONでsetup_instrumentsテーブル変更して運用すれば良いんじゃ、と思うかもしれませんがメモリ使用率がp_sがONと比較して多くなってしまいます。今回の環境ではMySQL再起動後、512スレッドで10分間、sysbenchを実行した場合、psコマンドで表示されるmysqldのRSSは以下のようになりました。

RSS
ケース1 8762784
ケース2 9605508
ケース3 9615032

900MB程度多くメモリを使用する結果となりました。ということで一応デメリットはあります。

まとめ

p_sを有効にしても無効と遜色の無い性能がread-onlyでは出る事が分かりました。ただ、ベンチマークは所詮ベンチマークなので実環境では異なる結果になる可能性がありますので必ず実環境に沿ったベンチマークを取得する事を推奨します。
その結果、記載したベンチマークの結果と同じ傾向になり、メモリ使用率の増加が許容出来るのであればp_sが有効で、必要になるまではsetup_instrumentsを変更(ENABLEDをNOに)して運用するのも有りだと思います。

なお、setup_instrumentsの設定値はMySQLを再起動するとデフォルトになるため、本番運用に組み込む場合は起動スクリプト等でENABLEDをNOに変更する処理を入れる必要があります。 追記参照。

以下の通り設定によりp_sで使うメモリ量は設定値により固定されるようなので極端に使用率が増えることは無いと考えられます。

@yoku8025さん、情報ありがとうございました。

追記

my.cnfのmysqldセクションに以下内容を記載すれば起動時からsetup_instrumentsテーブルのENABLEDをNOに出来ました

performance-schema-instrument='%=off'

sysbench 0.5のインストールと簡単な使い方

MySQLベンチマークとしてよく利用されるsysbenchのインストールと使い方について簡単にメモ。バージョンは0.5となります。

sysbench 0.5のダウンロード

(たぶん)sysbench 0.5はWebからダウンロード出来る場所がありません。ダウンロードはlaunchpadから行います。launchpadのアカウントの作成方法は割愛しますので予めアカウント作成しておいて下さい。

$ bzr branch lp:sysbench
Branched 116 revision(s).     
$ ls -ld sysbench
drwxr-xr-x 7 hiroi10 hiroi10 4096 Jun  1 04:07 sysbench
$ cd sysbench
$ ls -l
total 100
-rwxr-xr-x 1 hiroi10 hiroi10  3074 Jun  1 04:07 autogen.sh
-rw-r--r-- 1 hiroi10 hiroi10  7585 Jun  1 04:07 ChangeLog
drwxr-xr-x 2 hiroi10 hiroi10  4096 Jun  1 04:07 config
-rw-r--r-- 1 hiroi10 hiroi10 11267 Jun  1 04:07 configure.ac
-rw-r--r-- 1 hiroi10 hiroi10 17992 Jun  1 04:07 COPYING
drwxr-xr-x 3 hiroi10 hiroi10  4096 Jun  1 04:07 doc
-rwxr-xr-x 1 hiroi10 hiroi10  7122 Jun  1 04:07 install-sh
drwxr-xr-x 2 hiroi10 hiroi10  4096 Jun  1 04:07 m4
-rw-r--r-- 1 hiroi10 hiroi10   840 Jun  1 04:07 Makefile.am
-rwxr-xr-x 1 hiroi10 hiroi10 10266 Jun  1 04:07 missing
-rwxr-xr-x 1 hiroi10 hiroi10  1988 Jun  1 04:07 mkinstalldirs
-rw-r--r-- 1 hiroi10 hiroi10  3044 Jun  1 04:07 README
-rw-r--r-- 1 hiroi10 hiroi10   973 Jun  1 04:07 README-WIN.txt
drwxr-xr-x 5 hiroi10 hiroi10  4096 Jun  1 04:07 sysbench
-rw-r--r-- 1 hiroi10 hiroi10    26 Jun  1 04:07 TODO
$

コンパイルとインストール

事前にMySQL5.6.11をインストールしておいて下さい。MySQLがインストール済みであればコンパイル前までの準備はOKです。以下例はソースから/usr/local/mysql-5.6.11にインストール済みの場合です。

$ ./autogen.sh && ./configure --prefix=/usr/local/sysbench --with-mysql=/usr/local/mysql-5.6.11
$ make
$ sudo make install
$ /usr/local/sysbench/bin/sysbench --version
sysbench 0.5
$

以上でsysbenchの使用準備は完了です。

sysbench用のデータベースとMySQLアカウントを作成する

$ /usr/local/mysql-5.6.11/bin/mysql -uroot
mysql> create database sbtest;
mysql> grant all on sbtest.* to sbtest@localhost identified by 'sbtest-pw';
mysql> quit
$

テスト用データをロードしてみる

その前に0.5系から使われるようになった各種luaファイルをコピーしておきます。

$ pwd
/home/hiroi10/sysbench/sysbench/tests/db
$ mkdir /usr/local/sysbench/lua
$ cp -p *.lua /usr/local/sysbench/lua

ではロードします。以下の例は

  • テーブル数12
  • 1テーブルの行数3750000
  • 3並列でロード

となります。環境によって--num-threadsを増やすとより速くロードが行えます。なお、--num-threadsは--oltp-tables-countの約数となるようにして下さい。

$ /usr/local/sysbench/bin/sysbench \
  --test=/usr/local/sysbench/lua/parallel_prepare.lua \
  --db-driver=mysql \
  --oltp-tables-count=12 \
  --oltp-table-size=3750000 \
  --num-threads=3 \
  --mysql-db=sbtest \
  --mysql-user=root \
  --mysql-socket=/tmp/mysql-5.6.11.sock \
  run
$
$ ls -lh /usr/local/mysql-5.6.11/data/sbtest
total 11G
-rw-rw---- 1 mysql mysql   61 May 25 23:02 db.opt
-rw-rw---- 1 mysql mysql 8.5K May 25 23:30 sbtest10.frm
-rw-rw---- 1 mysql mysql 900M May 25 23:33 sbtest10.ibd
-rw-rw---- 1 mysql mysql 8.5K May 25 23:30 sbtest11.frm
-rw-rw---- 1 mysql mysql 904M May 25 23:33 sbtest11.ibd
-rw-rw---- 1 mysql mysql 8.5K May 25 23:30 sbtest12.frm
-rw-rw---- 1 mysql mysql 900M May 25 23:33 sbtest12.ibd
-rw-rw---- 1 mysql mysql 8.5K May 25 23:22 sbtest1.frm
-rw-rw---- 1 mysql mysql 900M May 25 23:25 sbtest1.ibd
-rw-rw---- 1 mysql mysql 8.5K May 25 23:22 sbtest2.frm
-rw-rw---- 1 mysql mysql 900M May 25 23:25 sbtest2.ibd
-rw-rw---- 1 mysql mysql 8.5K May 25 23:22 sbtest3.frm
-rw-rw---- 1 mysql mysql 900M May 25 23:25 sbtest3.ibd
-rw-rw---- 1 mysql mysql 8.5K May 25 23:25 sbtest4.frm
-rw-rw---- 1 mysql mysql 900M May 25 23:28 sbtest4.ibd
-rw-rw---- 1 mysql mysql 8.5K May 25 23:25 sbtest5.frm
-rw-rw---- 1 mysql mysql 900M May 25 23:28 sbtest5.ibd
-rw-rw---- 1 mysql mysql 8.5K May 25 23:25 sbtest6.frm
-rw-rw---- 1 mysql mysql 900M May 25 23:28 sbtest6.ibd
-rw-rw---- 1 mysql mysql 8.5K May 25 23:28 sbtest7.frm
-rw-rw---- 1 mysql mysql 900M May 25 23:31 sbtest7.ibd
-rw-rw---- 1 mysql mysql 8.5K May 25 23:27 sbtest8.frm
-rw-rw---- 1 mysql mysql 900M May 25 23:31 sbtest8.ibd
-rw-rw---- 1 mysql mysql 8.5K May 25 23:27 sbtest9.frm
-rw-rw---- 1 mysql mysql 900M May 25 23:31 sbtest9.ibd
$

ということでベンチマークを実行する準備が完了です。
なお、具体的に計ってませんがsysbench 0.4.12と比較すると並列にロード出来るのを抜きにしてもロードにかかる時間は0.5の方がかなり速いと感じました。

ベンチマークの実行

以下は自分がやってる実行例です。以下例はread-onlyですが--oltp-read-onlyをoffにすればread-writeのテストになります。(2013/06/13 オプション間違いがあったので直しました orz)

$ cat ./ro-bench.sh
#!/bin/sh

threads='8 16 32 64 128 256 512 1024'
DIR="テストケース名"

[ ! -d $DIR ] && mkdir $DIR
cp -pi /usr/local/mysql-5.6.11/etc/my.cnf $DIR/.

for thread in $threads; do
  echo "==== $thread ===="
  /usr/local/sysbench/bin/sysbench \
    --test=/usr/local/sysbench/lua/oltp.lua \
    --rand-init=on \
    --db-driver=mysql \
    --oltp-table-size=3750000 \
    --rand-type=uniform \
    --oltp-read-only=on \
    --oltp-tables-count=12 \
    --mysql-db=sbtest \
    --mysql-user=sbtest \
    --mysql-password=sbtest-pw \
    --mysql-socket=/tmp/mysql-5.6.11.sock \
    --max-time=180 \
    --max-requests=0 \
    --num-threads=$thread \
    run | tee $DIR/ro-$thread
    sleep 30
done
$

実際にベンチマークを取得する場合は事前にread-only、1024スレッドで60〜90秒程度を実行してバッファプールにデータ・インデックスの情報を載せてから実行しています。

$ /usr/local/sysbench/bin/sysbench \
>   --test=/usr/local/sysbench/lua/oltp.lua \
>   --rand-init=on \
>   --db-driver=mysql \
>   --oltp-table-size=3750000 \
>   --rand-type=uniform \
>   --oltp-read-only=on \
>   --oltp-tables-count=12 \
>   --mysql-user=sbtest \
>   --mysql-password=sbtest-pw \
>   --mysql-db=sbtest \
>   --mysql-socket=/tmp/mysql-5.6.11.sock \
>   --max-time=60 \
>   --max-requests=0 \
>   --num-threads=1024 \
>   run
sysbench 0.5:  multi-threaded system evaluation benchmark

Running the test with following options:
Number of threads: 1024
Random number generator seed is 0 and will be ignored


Threads started!

OLTP test statistics:
    queries performed:
        read:                            4549314
        write:                           0
        other:                           649902
        total:                           5199216
    transactions:                        324951 (5407.94 per sec.)
    deadlocks:                           0      (0.00 per sec.)
    read/write requests:                 4549314 (75711.09 per sec.)
    other operations:                    649902 (10815.87 per sec.)

General statistics:
    total time:                          60.0878s
    total number of events:              324951
    total time taken by event execution: 61384.6368s
    response time:
         min:                                  3.38ms
         avg:                                188.90ms
         max:                               1629.68ms
         approx.  95 percentile:             511.43ms

Threads fairness:
    events (avg/stddev):           317.3350/8.68
    execution time (avg/stddev):   59.9459/0.08

$

まとめ

OLTPなベンチマークは書いた情報で実行する事が可能かと思います。いかんせん0.5系の情報は少ないので海外のブログとか漁ると他にも情報が出てくると思います。他にもluaスクリプトは用意されているので軽く眺めてみると良いかと。私はまだ全部見れてませんけど…。
パラメータを変更しつつ何回かベンチマークしてるけどイマイチ載せようと思うような結果が出てなかったり…。とはいえそのうちベンチマーク結果も載せたいと考えてます。

gtidを使用した環境でのmysqldump

以前の日記Global Transaction IDを使ってレプリケーション構成とした際の制限でmysqldumpから新規にスレーブを作ろうとするとgtidが記録されなくてバイナリログ使わないとダメ、と書いたんだけど、5.6.10で試したら普通にスレーブを作成可能だったので訂正も含めて書きます。

よくあるmysqldump

MySQL5.5系まででgtidが存在しない環境では良く以下のようにmysqldumpを実行しているかと思います(InnoDBのみ利用の場合)。

# mysqldump --all-databases --single-transaction --master-data=2 > /path/to/dir/dump
または
# mysqldump --all-databases --single-transaction --master-data=2 | gzip > /path/to/dir/dump.gz
イベントスケジューラーとかその他色々使ってる場合
# mysqldump --all-databases --single-transaction --master-data=2 --triggers --routines --events > /path/to/dir/dump

なお、gtidを利用した環境では--triggers --routines --eventsオプションを使用しない場合は以下のようにWarningが出力されます。

# mysqldump --all-databases --single-transaction --master-data=2 > /tmp/dump
Warning: A partial dump from a server that has GTIDs will by default include the GTIDs of all transactions, even those that changed suppressed parts of the database. If you don't want to restore GTIDs, pass --set-gtid-purged=OFF. To make a complete dump, pass --all-databases --triggers --routines --events. 
#

gtid環境でmysqldumpを取得した場合のダンプファイル

上記のmysqldump実行例の以下内容でダンプを取得します。

# mysqldump --all-databases --single-transaction --master-data=2 --triggers --routines --events > /path/to/dir/dump

ダンプファイルの中身を覗いてみます。

# mysqldump --all-databases --single-transaction --master-data=2 --triggers --routines --events > /tmp/dump
# head -30 /tmp/dump 
-- MySQL dump 10.13  Distrib 5.6.10, for Linux (x86_64)
--
-- Host: localhost    Database: 
-- ------------------------------------------------------
-- Server version	5.6.10-log

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
SET @MYSQLDUMP_TEMP_LOG_BIN = @@SESSION.SQL_LOG_BIN;
SET @@SESSION.SQL_LOG_BIN= 0;

--
-- GTID state at the beginning of the backup 
--

SET @@GLOBAL.GTID_PURGED='71803be2-7816-11e2-8c99-5254003e1cec:1-665';

--
-- Position to start replication or point-in-time recovery from
--

-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000006', MASTER_LOG_POS=197930;

ここで見慣れない以下内容が記録されています。

SET @@GLOBAL.GTID_PURGED='71803be2-7816-11e2-8c99-5254003e1cec:1-665';

gtid関連のパラメータとして、MySQL5.6.10では以下パラメータが存在しています。以下はMaster側のダンプを取得したMySQLの内容です。

mysql> show global variables like '%gtid%';
+--------------------------+--------------------------------------------+
| Variable_name            | Value                                      |
+--------------------------+--------------------------------------------+
| enforce_gtid_consistency | ON                                         |
| gtid_executed            | 71803be2-7816-11e2-8c99-5254003e1cec:1-665 |
| gtid_mode                | ON                                         |
| gtid_owned               |                                            |
| gtid_purged              |                                            |
+--------------------------+--------------------------------------------+
5 rows in set (0.00 sec)

mysql> show variables like '%gtid%';
+--------------------------+-----------+
| Variable_name            | Value     |
+--------------------------+-----------+
| enforce_gtid_consistency | ON        |
| gtid_executed            |           |
| gtid_mode                | ON        |
| gtid_next                | AUTOMATIC |
| gtid_owned               |           |
| gtid_purged              |           |
+--------------------------+-----------+
6 rows in set (0.00 sec)

mysql> 

global無しを書いたのはgtid_nextはsessionのみのパラメータのためです。

リストアしてみる

今回ポイントとなるのはgtid_executedとgtid_purgedの2つ。先に記載のダンプファイルの内容から、リストアした場合はgtid_purgedに値が設定されることが分かります。実際に空の、新しく立ち上げたMySQLへリストアを行います。

まずはリストア前のgtid関連のパラメータの状態

mysql> show global variables like '%gtid%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| enforce_gtid_consistency | ON    |
| gtid_executed            |       |
| gtid_mode                | ON    |
| gtid_owned               |       |
| gtid_purged              |       |
+--------------------------+-------+
5 rows in set (0.00 sec)

mysql> 

リストアを行って確認します。

# mysql < /tmp/dump
# mysql
mysql> show global variables like '%gtid%';
+--------------------------+--------------------------------------------+
| Variable_name            | Value                                      |
+--------------------------+--------------------------------------------+
| enforce_gtid_consistency | ON                                         |
| gtid_executed            | 71803be2-7816-11e2-8c99-5254003e1cec:1-665 |
| gtid_mode                | ON                                         |
| gtid_owned               |                                            |
| gtid_purged              | 71803be2-7816-11e2-8c99-5254003e1cec:1-665 |
+--------------------------+--------------------------------------------+
5 rows in set (0.00 sec)

mysql> 

gtid_executedをgtid_purgedがセットされました。ダンプファイルに書いてあったのはgtid_purgedだけだったのに?

では公式ドキュメントのgtid_purgedgtid_executedを見てみましょう。以下ざっくりと。

  • gtid_executed
    • 適当にまとめると、globalスコープの場合はgtid_executedに書かれてるgtidまでバイナリログに書いてあるよ、って事だと思います。read_onlyなパラメータで空にしたいならreset master;実行してね。5.6.9より前はgtid_doneってパラメータ名だったよ。
  • gtid_purged
    • こちらも適当にまとめると、gtid_purgedに書かれているgtidまではバイナリログから削除されてるよ。5.6.9より前はgtid_lostってパラメータ名。gtid_executedが空の場合だけset可能だよ。

なんか訳すと矛盾してるような気分になりますが、gtid_executedは設定されているgtidまでは実行済みだよってことだし、新規にダンプファイルから上記の流れでスレーブを作った場合はバイナリログにリストアされた内容は記録されていなかったりします。

# mysqlbinlog ./mysql-bin.000004
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#130309  2:22:35 server id 239  end_log_pos 120 CRC32 0x4fbf920d 	Start: binlog v 4, server v 5.6.10-log created 130309  2:22:35
# Warning: this binlog is either in use or was not closed properly.
BINLOG '
Wx46UQ/vAAAAdAAAAHgAAAABAAQANS42LjEwLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAEzgNAAgAEgAEBAQEEgAAXAAEGggAAAAICAgCAAAACgoKGRkAAQ2S
v08=
'/*!*/;
# at 120
#130309  2:22:35 server id 239  end_log_pos 191 CRC32 0x28155e76 	Previous-GTIDs
# 71803be2-7816-11e2-8c99-5254003e1cec:1-665
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
#

なんで?と思われた方、上の方で書いたダンプファイルのhead -30の結果を再度見てみましょう。必要なポイントだけ抜粋したのが以下になります。

SET @MYSQLDUMP_TEMP_LOG_BIN = @@SESSION.SQL_LOG_BIN;
SET @@SESSION.SQL_LOG_BIN= 0;

SQL_LOG_BIN=0が発行されています。よってリストアで発行された更新処理はバイナリログに記録されません。gtid_purgedがgtid_executedが同じなのは間違いではないことが分かります。

ということでスレーブではgtid_executedに設定されているgtidまで更新内容が反映済みという状態となります。この状態でchange master toでmaster_auto_position=1でレプリケーションを開始します。

mysql> change master to master_host='192.168.1.237', master_user='repl', master_password='repl-pw', master_auto_position=1;                                       
Query OK, 0 rows affected, 2 warnings (0.03 sec)

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: 
                  Master_Host: 192.168.1.237
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: 
          Read_Master_Log_Pos: 4
               Relay_Log_File: mysql-relay-bin.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File: 
             Slave_IO_Running: No
            Slave_SQL_Running: No
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 0
              Relay_Log_Space: 151
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 0
                  Master_UUID: 
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: 
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 71803be2-7816-11e2-8c99-5254003e1cec:1-665
                Auto_Position: 1
1 row in set (0.00 sec)

mysql> 

正しくExecuted_Gtid_Setにgtidが設定されている事が分かります。

Executed_Gtid_Set: 71803be2-7816-11e2-8c99-5254003e1cec:1-665

ではstart slave;を行いましょう。

mysql> start slave;
Query OK, 0 rows affected (0.02 sec)

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.1.237
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000006
          Read_Master_Log_Pos: 200338
               Relay_Log_File: mysql-relay-bin.000007
                Relay_Log_Pos: 2816
        Relay_Master_Log_File: mysql-bin.000006
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 200338
              Relay_Log_Space: 3230
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 237
                  Master_UUID: 71803be2-7816-11e2-8c99-5254003e1cec
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 71803be2-7816-11e2-8c99-5254003e1cec:666-673
            Executed_Gtid_Set: 71803be2-7816-11e2-8c99-5254003e1cec:1-673
                Auto_Position: 1
1 row in set (0.00 sec)

mysql> 

問題無くレプリケーションが開始されました。良いですね。gtid環境でもmysqldumpが普通に使えます。

その他

今回は書きませんが、gtidを使ったSlaveサーバから--dump-slave=2とかでダンプを取った場合も同様に新しいSlaveを作成可能です。但し、その場合はリストアするMySQLは極力真っ新な状態の物を使う事を推奨します。クラッシュセーフなSlaveにするために以下パラメータをTABLEにしてる場合、バイナリログ、リレーログファイルの情報がダンプ元のサーバの情報になってしまうためです。

master_info_repository=TABLE
relay_log_info_repository=TABLE

--dump-slaveを使う事が最初から予定されている場合は全てのMaster, Slaveで以下のようにバイナリログ、リレーログファイル名を統一しておくと良いでしょう。手間が掛からなくなります。

log-bin=mysql-bin
relay_log=mysql-relay-bin

まぁ"ホスト名"-binとかの形には本来はしない方が良い(個人的にホスト名が付くのは非推奨)ので、既にちゃんと指定してるよ、という方も多いかと思います。

また、gtidを利用してない環境にリストアするためにダンプを取得する場合はmysqldumpに--set-gtid-purged=OFFを付けます。あまり無いだろうけど、あえて5.5系とか。このオプションを付ける事でgtidを使用した環境からのダンプファイルに以下内容が出力されなくなります。

SET @@GLOBAL.GTID_PURGED='71803be2-7816-11e2-8c99-5254003e1cec:1-665';

終わりに

MySQL 5.6.10ではgtidを利用した環境でもgtidを特に意識せず、mysqldumpによるダンプファイルから新規にSlaveが作成出来ます。gtid環境でネックだなぁ、と思ってた内容が一つ解消したのは個人的には嬉しい所です。