なからなLife

geekに憧れと敬意を抱きながら、SE、ITコンサル、商品企画、事業企画、管理会計、総務・情シス、再び受託でDB屋さんと流浪する人のブログです。

RDS for MySQLで変更すべきパラメータチューニング

呼ばれたきがしたので

soudai.hatenablog.com

なお、InnoDB限定のお話ですよ。MyISAMを(システムテーブル以外で)使ったことない若輩者なので。

ちょっと余裕がないこともあり、思いつく最小限のことだけ書きます。追加で思いついたら後ほど&温かいフォロー(というマサカリ?)歓迎。

checkpointに影響がある値

innodb_log_file_size

Redoログのファイルサイズです。

MySQLのデフォルトは「50331648 Byte(48MB)」、RDSのデフォルトは「134217728 Byte(128MB)」。大きなバッチ処理がなければ間に合うかも知れないですが、広げたほうがよいでしょう。

適切な値の範囲は、1M バイトから 1/バッファープールの N 番目のサイズまでです。ここで、N はグループ内のログファイルの数です。
https://dev.mysql.com/doc/refman/5.6/ja/innodb-parameters.html#sysvar_innodb_log_file_size

実はこの一節、日本語版マニュアル(MySQL5.6)だけにある記述なんですよね。


グループ内のログファイルの数を決めるパラメータは「innodb_log_files_in_group」で、デフォルト「2」となっています。これは特に変えなくても良いと思います。

「1/バッファープールの N 番目のサイズ」は、ちょっと意味わかりにくい&英語原文がないので推測ですが、おそらく「innodb_buffer_pool_instances」のことを言っているのではないかと思います。
これは、バッファプールの分割数のことで、バッファープールの領域を分割管理することで、メモリ上の同じ場所にアクセスする際に発生するロック(セマフォ)衝突を軽減する効果があります。

innodb_buffer_pool_instances」のデフォルトは「8」で、セマフォ競合が出まくっていて、かつ、セマフォ競合が多く発生している環境以外では、変更しなくても良いと思います。

かたやバッファープールは「innodb_buffer_pool_size」ですが、これはRDSではインスタンス実メモリサイズの75%を計算して自動適用するように作られています(めっちゃ便利です)し、固定値に変えることもできます。



よって、先程の表現にある「適切な値の範囲」の上の値は、
{DBInstanceClassMemory*3/4} / innodb_buffer_pool_instances * innodb_log_files_in_group(2)
ということになりますね。

メモリ4GBのインスタンスだと、4096 * 0.75 / 8 * 2 = 768 MB、っていう具合です。


ある時間帯に大量更新が走る場合、このチェックポイント処理の影響で処理が遅くなることがありますので、あくまで目安です。
実環境での計測で、処理時間の要件とメモリの状態、他処理への影響などに鑑みて決定しましょう。




innodb_io_capacity/innodb_io_capacity_max

チェックポイント時に、バッファ上のデータをストレージ上のデータファイル(ibdファイル)に同期する際の速度(IOPS)の値です。デフォルトは「200」と「2000(_max)」です。
これ、結果maxまで使ってしまうのに、前者のパラメータがある意味は未だに理解できてないです。とりあえず_max重要。


RDSの裏側は、ハッキリ言って「EC2+EBS1本」ですので、ストレージI/O性能はEC2+EBS1本のときの構成に準じます。
なので、ストレージI/O性能は、PIOPSの指定値、あるいば、gp2のストレージサイズ基準のベースライン(1 GBあたり3 IOPS)/バーストラインで決まります。


ポイントは、MySQLのストレージI/Oは、ibdファイルの同期処理だけではない、ということ。
そこの考慮をせずに、「innodb_io_capacity_max=アタッチしたEBSの性能上限」っていう設定をすると、チェックポイントでストレージI/O性能を使い切ってしまって、別のストレージI/O処理が詰まる可能性があります。
ベースライン3000 IOPS以下(1024 GB 以下)の場合、3,000 IOPSまでバーストするので、ベースラインを設定していても救いはありますが、PIOPS利用時やgp2で1024GB以上のストレージを使っている場合は、性能上限よりも小さな数値を指定しましょう。






MySQLのチェックポイントのメカニズムとか

なぜinnodb_log_file_sizeを大きくするとチェックポイントが起こりにくくなるか、というお話は、瀬島さんのこの資料を10回位読むと良いです。まじで2桁回は読んでる。


www.slideshare.net



他のパラメータ

max_connections

MySQLのデフォルトの「151」っていうのも、これはこれで異様に小さい値です。
RDSだと「{DBInstanceClassMemory/12582880}」という式がはいっています。これ、ハッキリ言って異常に大きな数字がでます。

そんなにつないでこないかも知れませんが、フツーに計算するとパンクする値が算出されるので、ここは設計上の接続数をちゃんと積み上げて固定しておいたほうが安全かと思います。

パラメータ一覧

そーだいさんのエントリからは、「パラメーター解体新書」への誘導がされていました。

MySQLの場合、公式ドキュメントがあのような構造を取っている(一覧、デフォルト、取りうる範囲、動的変更可否、その他説明や、カテゴリ単位での説明ページへの誘導)を取っているので、調べやすいです。
とにかく公式ドキュメントを読みましょう。日本語は5.6用しかないですが、同じ項目記述のバージョン間比較遷移がしやすいように工夫されていますし(これはPostgreSQLのドキュメントも)、あとはGoogle先生の翻訳パワーでなんとかなります。



キャパシティ変更に要注意

開発用と試験、本番用で異なるインスタンスを立てることが多いと思いますが、その際、インスタンスのメモリ値に連動するパラメータとそうでないパラメータがあることに注意です。
インスタンスのメモリサイズ連動パラメータと異なり、ストレージI/O系は非連動ですので、要注意です。

まとめ

  • RDS MySQLでもチューニングポイントの筆頭は、チェックポイント処理絡み。
  • いくらDBaaSといっても、生のアーキを理解してチューニングすべきところがある。


MySQLにも、PostgreSQLのような「内部構造からわかる」本がほしいなと思ったけど、奥野さんの鍵本やオライリーのハイパフォーマンスMySQLからあんまり変わってなかった。
で、最近、MySQLのガッツリ系で新しい本が出てきてないので、やっぱりコレを推しておきます。