MySQL 5.7のマニュアルにも書かれているように、MySQL 5.7.5からmysqldを再起動させずにバッファプールのサイズを変えることができるようになった。
これにより、SET GLOBAL innodb_buffer_pool_size = xxxxとコマンドを実行して、バックグラウンドでのサイズ変更ジョブを実行できるようになった。サイズ変更の進捗と状況は、innodb_buffer_pool_resize_status変数か、エラーログから確認できる。
メモリの確保と解放処理の影響を最小化し、トランザクション処理関連のタスクをブロックしてしまう大きなメモリコピー処理を避けるため、サイズ変更は一定のサイズのチャンク単位で行われる。InnoDBは同じサイズのバッファプールインスタンスを使うようにデザインされているので、バッファプールサイズの総量は、「innodb_buffer_pool_instances x innodb_buffer_pool_chunk_size」という乗算結果に(上限が)調整される。
バッファプール内の全てのページ割り当て、解放、検索のコールは、サイズ変更処理のクリティカルパスでのみブロックされる。クリティカルパスは、以下の部分から構成される。
- OSからメモリを割り当て、OSに対しメモリを解放する
- 必要なら、内部ハッシュテーブル(page_hash、zip_hash)のサイズを変更する
クリティカルパスの時間は、OSのメモリマネージャのパフォーマンスに大きく依存する。
バッファプールを縮小するサイズ変更操作の準備フェーズには時間がかかる可能性があるが、並列で動くトランザクション処理関連タスクをブロックすることはない。準備フェーズは以下の要素からなる。
- 小さなサイズに収まるようにページ数を削減する
- 解放されるべきチャンクからページを移動する
当然のことだが、小さくなるはずのバッファプールにダーティページが多すぎると、それらをディスクに書き込み、解放する必要がある。この処理はディスクIOに大きな影響を与え、その実行中に他のトランザクション関連タスクに間接的な影響を与える可能性がある。
もう1つ注目すべきは、チャンク内のページを解放するためにトランザクションがロックを確保した時には、ページの移動はトランザクションが終わるまで待たされることだ。そのため、トランザクションのスループットが高い時や、実行時間の長いトランザクションがある時には、バッファプールのサイズ変更操作がブロックされる可能性がある。一定以上待たされた処理については、その操作を待たせたりブロックした原因となった疑いのあるトランザクションの情報とともに、エラーログファイルに記録される。
最後に、1つ注意すべき制限事項がある。バッファプールのサイズ変更処理中は、アダプティブハッシュインデックス(AHI)が無効になる。これは、AHIがバッファプールページを使用しており、それが有効な時には必要なページを移動するのが非常に難しいためだ。
今のところここまで。この新機能についてのフィードバックを楽しみに待っている!質問やバグ遭遇の報告は、サポートチケットをオープンするか、バグ報告してほしい。MySQLご利用ありがとうございます!