はじめに
MySQLが稼働するDBサーバでは、可能な限りMySQL以外のプロセスは稼働していない状況が推奨されます。それはプロセス間のサーバリソース(CPU、メモリなど)の競合や、問題発生時の原因切り分けの煩雑さを避けるためです。
とはいえ、実際には諸々の事情から、他のプロセスと同居させざるを得ないケースもあるかと思います。
その場合、他プロセスが予期せぬ挙動でCPUリソースの大部分を使用してしまい、MySQLが割を食ってしまうことも考えられます。本稿では、そうしたケースを想定したMySQL性能試験について触れたいと思います。
stress-ng について
意図的なCPU負荷をかけるツールは様々ありますが、今回は「stress-ng」コマンドを使用します。
このコマンドは、公式マニュアルの記述の通り、200種類以上ものストレステストを実現できます。また、大半のLinuxに対応しており非常に高い汎用性を有しています。
テスト概要
Oracle公式リポジトリからyumインストールしたMySQL8.0.14に対して、sysbenchで read_write の負荷試験を行います。
その際に、stress-ngコマンドを使って負荷をかけるCPUコア数を 0コア → 2コア → 4コア → 6コア → 8コア と引き上げていき、sysbenchのスコアの変動を確認します。
環境構築
この試験では、以下のようなサーバを使用します。
vCPU : 8 core
RAM : 64GB
MySQL8.0.14をインストールし、起動します。
1 2 3 4 |
$ sudo rpm -ivh https://dev.mysql.com/get/mysql80-community-release-el7-2.noarch.rpm $ sudo yum install -y mysql-community-server $ sudo vi /etc/my.cnf $ sudo systemctl start mysqld |
※ my.cnfには以下の項目だけ追加しています
1 2 3 4 5 6 7 8 |
[mysqld] innodb_buffer_pool_size = 20G innodb_log_file_size = 512M log_bin server_id = 10 slow_query_log = ON long_query_time = 2 default_authentication_plugin=mysql_native_password |
次に、sysbench 1.0をインストールします。
1 2 |
$ curl -s https://packagecloud.io/install/repositories/akopytov/sysbench/script.rpm.sh | sudo bash $ sudo yum install -y sysbench |
stress-ngコマンドは、epel リポジトリに含まれています。もしインストールされていない場合はリポジトリを準備してから、stress-ngコマンドをインストールしましょう。
1 2 |
$ sudo yum install -y epel-release $ sudo yum install -y stress-ng |
テスト手順
まずはsysbenchのデータをロードします。
–table-size = 1000000 / –tables = 10 オプションをつければ、100万行のテストテーブルが10個作られます。
1 2 3 4 5 6 |
$ mysql -u sbuser -pMySQL8.0 mysql> create database sbtest; mysql> create user `sbuser`@`localhost` identified by "MySQL8.0"; mysql> grant all on sbtest.* to `sbuser`@`localhost`; mysql> exit |
1 2 3 4 5 6 7 8 9 |
$ sysbench oltp_read_write --db-driver=mysql --mysql-host=localhost --mysql-user=sbuser \ --mysql-password=MySQL8.0 --tables=30 --table-size=1000000 --threads=30 prepare $ sudo ls -lh /var/lib/mysql/sbtest/ 合計 7.1G -rw-r----- 1 mysql mysql 240M 2月 13 11:05 sbtest1.ibd -rw-r----- 1 mysql mysql 240M 2月 13 11:05 sbtest10.ibd -rw-r----- 1 mysql mysql 240M 2月 13 11:05 sbtest11.ibd ... |
ロード後のデータディレクトリは丸ごとバックアップとして任意の場所にコピーします。
ベンチマーク実行後、このバックアップを毎回リストアしてテストを繰り返します。
1 2 3 |
$ sudo systemctl stop mysqld $ sudo cp -rp /var/lib/mysql /var/lib/mysql_backup $ sudo systemctl start mysqld |
準備が完了したら、以下の4パターンでベンチマークを実施します。
同じ試験を2回ずつ行います。なお、sysbenchのコマンドは全て同じです。
① stress-ng 実行なし
② stress-ng 実行(2コア)
③ stress-ng 実行(4コア)
④ stress-ng 実行(6コア)
⑤ stress-ng 実行(8コア)
【stress-ng のオプション】
・–cpu:CPUの負荷試験を行う場合に指定する。数値には使用するCPUのコア数を指定する。
・-l:CPUの使用率を指定する。今回は90%に固定する。
・-t:実行時間を指定する。今回はsysbenchよりも長い15分(15m)に固定する。
※ 2コアを使用するstress-ngコマンドの実行例(sysbench実行前に行う)
1 |
$ sudo stress-ng --cpu 2 -l 90 -t 15m |
topコマンド → “1”を入力、でコアごとの使用率を見ると以下のようになります。
1 2 3 4 5 6 7 8 |
$ top Tasks: 242 total, 3 running, 239 sleeping, 0 stopped, 0 zombie %Cpu0 : 90.7 us, 0.0 sy, 0.0 ni, 9.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 : 3.7 us, 1.0 sy, 0.0 ni, 95.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 : 5.4 us, 1.0 sy, 0.0 ni, 93.6 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 : 90.7 us, 0.3 sy, 0.0 ni, 9.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu4 : 5.7 us, 1.3 sy, 0.0 ni, 93.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st ... |
【sysbench 実行コマンド】
1 2 |
$ sysbench oltp_read_write --db-driver=mysql --mysql-host=localhost --mysql-user=sbuser \ --mysql-password=MySQL8.0 --tables=30 --table-size=1000000 --threads=30 --time=600 run > ./1_no_stress_1.log |
テスト結果
TPS | QPS | Latency (avg) | |
---|---|---|---|
① stress-ng 実行なし 1回目 | 890.98 | 17819.68 | 33.66 ms |
① stress-ng 実行なし 2回目 | 904.07 | 18081.58 | 33.18 ms |
② stress-ng 実行(2コア)1回目 | 822.36 | 16447.33 | 36.47 ms |
② stress-ng 実行(2コア)2回目 | 827.55 | 16551.16 | 36.24 ms |
③ stress-ng 実行(4コア)1回目 | 706.80 | 14136.06 | 42.44 ms |
③ stress-ng 実行(4コア)2回目 | 677.57 | 13551.51 | 44.27 ms |
④ stress-ng 実行(6コア)1回目 | 594.39 | 11887.96 | 50.46 ms |
④ stress-ng 実行(6コア)2回目 | 580.92 | 11618.44 | 51.63 ms |
⑤ stress-ng 実行(8コア)1回目 | 515.01 | 10300.22 | 58.24 ms |
⑤ stress-ng 実行(8コア)2回目 | 501.54 | 10030.79 | 59.80 ms |
追加テスト
折角なので、以下のパターンも計測してみました。
⑥ stress-ng 実行(8コア, 20%)
⑦ stress-ng 実行(8コア, 40%)
⑧ stress-ng 実行(8コア, 60%)
⑨ stress-ng 実行(8コア, 80%)
⑩ stress-ng 実行(8コア, 100%)
結果は以下の通りです。
TPS | QPS | Latency (avg) | |
---|---|---|---|
⑥ stress-ng 実行(8コア, 20%)1回目 | 842.71 | 16854.33 | 35.59 ms |
⑥ stress-ng 実行(8コア, 20%)2回目 | 790.72 | 15814.42 | 37.93 ms |
⑦ stress-ng 実行(8コア, 40%)1回目 | 739.10 | 14782.17 | 40.58 ms |
⑦ stress-ng 実行(8コア, 40%)2回目 | 716.16 | 14323.36 | 41.88 ms |
⑧ stress-ng 実行(8コア, 60%)1回目 | 648.75 | 12975.13 | 46.23 ms |
⑧ stress-ng 実行(8コア, 60%)2回目 | 631.46 | 12629.26 | 47.50 ms |
⑨ stress-ng 実行(8コア, 80%)1回目 | 557.09 | 11141.96 | 53.84 ms |
⑨ stress-ng 実行(8コア, 80%)2回目 | 540.26 | 10805.37 | 55.52 ms |
⑩ stress-ng 実行(8コア, 100%)1回目 | 339.04 | 6780.82 | 88.47 ms |
⑩ stress-ng 実行(8コア, 100%)2回目 | 328.70 | 6574.01 | 91.25 ms |
まとめ
上記のように、CPUの負荷をあげるにつれてsysbenchのスコアが低くなっていることが分かります。これはstress-ngコマンドではなく、通常のアプリケーションであっても、スコア低下率に差はあれ同様の傾向がみられると考えられます。
もし、DBサーバにMySQL以外のプロセスを同居させる場合は注意してください。
しかし、一方でCPU負荷が高い状態でもMySQLは一定以上の性能が出せることも確認できました。もし、MySQLの最低限の性能をみたいケースなどでも、こうした性能試験は便利そうです。
stress-ngコマンドはCPU以外にも様々な負荷シナリオを実現できます。もしよければお手元のMySQLサーバで色々と試してみてください。