読者です 読者をやめる 読者になる 読者になる

MySQLのグループコミットとそれに連想するもの

グループコミット

  • MySQLでは、バイナリログへの書き込みのタイミングを、sync_binlogによってユーザが指定することができる。具体的にはsync_binlogの値によって、何回コミットを行ったらバイナリログをディスクにフラッシュするか、を指示するため、sync_binlog=1を設定することでコミット毎にバイナリログをディスクにフラッシュすることができ、耐障害性を上げることができる。ただし、その結果として書き込み性能は下がることになる。sync_binlog=0を設定することで、バイナリログのフラッシュのタイミングをOSに委ねることにより書き込み性能は上がるが、マスタの障害時には、マスタ側では最新の内容をディスクに保存できているにも関わらず、スレーブ側に最新の状態でレプリケーションすることが出来ず、マスタとスレーブで一貫性が保てなくなる。

  • MySQL5.6では、複数コミットをまとめた上で、バイナリログのフラッシュを実施するための機能である、グループコミットのsync_binlog=1の場合の性能が向上されている。これにより、sync_binlog=1を設定していても、書き込み性能をそれほど落とすことなく運用することが可能になった。グループコミットにおける複数コミットのまとめ方は、あるトランザクションAにおいてディスクへのフラッシュが行われている間に、別のトランザクションBがそのフラッシュを待っている間、また別のトランザクションCがフラッシュを行おうとした際に、Aによるフラッシュが完了した際に、BとCをまとめてフラッシュすることによって、書き込み性能を上げるものである。

アグリゲーション

  • 複数コミットをまとめることで性能を上げるのは、アグリゲーションによる最適化手法と言える。例えば、無線LANにおいて802.11nでは、フレームを複数まとめて一つのフレームとして送信するA-MSDU/A-MPDUというアグリゲーション手法(ヘッダ圧縮)が取り入れられており、これによってスループットが向上している。この場合、どのようにMACフレームをまとめているのか、という点を考えてみると、アクセスポイントからフレームを送信する際、CSMA/CAにおけるキャリアセンスによってチャネルが占有されていることを検知して送信タイミングをインターバル+バックオフの分だけ遅延する場合、その間にアクセスポイントに到達した宛先が同じフレームをまとめ上げて一つのフレームを形成し、次にチャネルが空いているタイミングで送信している、と考えられる。あるいはもっと単純に、送信レートが低い場合などは、一つのフレームを送信している間に別のフレームが到達するケースも考えられる。

  • しかし、チャネルが一つのアクセスポイントによって占有できる場合、あるいは受信感度が良く最大送信レートを持続できる場合、あるフレームの送信中に別のフレームが到達する頻度が少なくなるため、アグリゲーションが起きづらい、ということが考えられる。そうなると、チャネルの状態が悪い場合(より混雑している、距離が遠いことなどによって、より受信感度が悪い)の方が、アグリゲーションによる恩恵によってスループットが上がるケースもあり得る、と考えることができる。ただし、最大スループットを測定するようなベンチマークの場合は、アグリゲーションが起きやすくなっているため、このような逆転は起こらない、とも考えられる。

  • アグリゲーションなど、リソースを蓄積するための期間を設ける必要がある手法を用いる場合に、その期間がある定まった値になると、必ずその期間だけ遅延が挿入されていることになる。下のリンクで紹介されているPostgreSQLに実装されていたcommit_delayが、それに当たるのではないかなと推測している。スループットとRTTは別々のベンチマークが必要になることには注意が必要である。

Nagle Algorithm

  • もう一つ「まとめる」と聞いて連想するのが、TCPのNagle Algorithm。小さいデータをまとめて一つのパケットとして送ることによって、パケット数を減らす効果がある。ACK待ちの場合に、次のMSS以下のサイズのデータはすぐには送らずに、ACKが来るまで待って、一つのパケットに詰め込んで送る。ただしこれも諸刃の剣であり、利点としてパケット中のヘッダに対するペイロードの割合が上がるので帯域使用率は上昇するものの、欠点としてはリアルタイム性が下がるので、アプリケーションによっては問題になる。Nagle Algorithmによる遅延を回避するためには、ソケットオプションにTCP_NODELAYを指定する。

Thanks to

Yoshinori Matsunobu's blog: Making slave pre-fetching work better with SSD