Aurora MySQL のバイナリログのパフォーマンス影響について改めて調べてみた
Aurora MySQL で RDS Blue/Green Deployments を使うにはバイナリログを有効にする必要があります。
Aurora MySQL 1 の頃はバイナリログを有効にすると、パフォーマンスへの影響があるので必要なときだけ有効にすることが推奨されていました。 re:Post の「Aurora MySQL 互換 DB クラスターのバイナリログの保持期間を長くするにはどうすればよいですか?」にも次のように記載されています。
注: Aurora MySQL 互換 DB クラスターでバイナリログを有効にすると、パフォーマンスに以下の影響が生じます。
- 追加の書き込みオーバーヘッドが発生する(必要な場合にのみ有効にしてください)
- バイナリログのリカバリプロセスにより、再起動時のエンジンの起動時間が長くなる
知識をアップデートするために改めて調べてみると、Aurora MySQL 2.10 以降はバイナリログのパフォーマンスへの影響は気にしなくても良さそうです。以下でその理由を見ていきます。
binlog I/O cache
1 つ目の理由は、Aurora MySQL 2.10 で導入された binlog I/O cache という機能です。 db.t2 / db.t3 を除くインスタンスクラスではデフォルトで有効になっています。
直近にコミットされたバイナリログのイベントをキャッシュすることで、binlog dump スレッド(バイナリログの内容をレプリカに送信するスレッド)のパフォーマンスを向上させています。
Aurora MySQL 2.09 以前は aurora_binlog_replication_max_yield_seconds
というパラメータで調整していました。このパラメータを使うと binlog dump スレッドが指定した秒数待つようになり、バイナリログの書き込みと読み込みの競合を減らすことでパフォーマンスを改善していました。しかし、言い換えればレプリケーション遅延が大きくなることを意味します。 binlog I/O cache はこの問題も解決してくれます。
実際に Aurora MySQL 2.11.2 のクラスターでバイナリログを有効にしてみましたが、Datadog APM では差は見られませんでした。
enhanced binlog
2 つ目の理由は、最近発表されたばかりの Aurora MySQL 3.03 以降で使える enhanced binlog という機能です。この機能は binlog I/O cache と違い、明示的に有効にする必要があります。
大前提としてバイナリログはデータベースへの変更のコミット順序を維持しなければなりません。この処理に 2 フェーズコミットが採用されていますが、この調整のために書き込みの待ち時間が発生します。
enhanced binlog はトランザクションログとバイナリログのストレージを分離し、バイナリログは最適化された専用のストレージノードに書き込みます。そして、バイナリログのソートと順序付けをデータベースエンジンではなくストレージレイヤーで行っています。
The first innovation comes from separating storage of the transaction log from storage of the binlog. Instead of using the same storage node for storing both the transaction and binlog, Aurora MySQL now stores the binlog on specialized storage nodes optimized for binlog. These storage nodes have added logic which make it possible for the database engine to push down the sorting and ordering of binlog to the storage layer.
MySQL の binlog の仕組み(上記のブログ記事では community binlog と呼んでいます)を Aurora 向けに再設計したのが enhanced binlog と言えるでしょう。
enhanced binlog は別のストレージに保存されるためバックアップに含まれないなどの制約もあります。なので、binlog I/O cache でも満足できない場合に enhanced binlog を検討すると良さそうです。