MySQL 5.6 では innodb_flush_log_at_trx_commit の意味が MySQL 5.5 と違う
タイトルの通り、 innodb_flush_log_at_trx_commit=1 の場合も、トランザクションログが fsync されません。トランザクションがディスクに書かれるシーケンスは次のようになります。
1. prepare (fsync) 2. write binlog (grouped, fsync) 3. commit
このうち 1 は従来通り各スレッドで並列に実行され、 2 と 3 が昨日紹介した sql/binlog.cc の MYSQL_BIN_LOG::ordered_commit() の中のでグループ化されてシーケンシャルに実行される処理です。 この ordered_commit() は先頭で
thd->durability_property= HA_IGNORE_DURABILITY;というようなフラグを立てています。このフラグは MySQL のソースコードの中で参照しているのは storage/innobase/trx/trx0trx.cc だけで、 HA_IGNORE_DURABILITY の時は flush_log_at_trx_commit=0 のように振る舞い、フラッシュ (fsync) を実行しません。
この場合、データの永続性は prepare されたトランザクションの内容と binlog で担保されます。 クラッシュリカバリの時は、 binlog を読み込んで、そこに書かれているprepare済みトランザクションをコミットしていきます。 (このため、クラッシュしたマシンからDBをコピーしてMySQLを再起動する場合など、binlogのコピーをサボるとコミットしたはずのトランザクションが消えてしまうので注意が必要です。今のところリカバリに読まれるのは最後の binlog だけで、 binlog のローテート時はトランザクションログにも fsync します)
最終的に、トランザクションごとの fsync の数は、 MySQL 5.5 の場合は (sync_binlog=0 の場合) 2回だったのに対して、 MySQL 5.6 では2回のうち1回は負荷が高くなるほどグループ化されて複数のコミットを1度で fsync されることになります。この点で MariaDB の方が速そうというのは勘違いでした。
この辺りはドキュメントが整ってなくて、 MySQL-internals に質問のスレッドが立っているのでそこが参考になります。
これKristianがMonty Program ABの人で、MatsがOracleの人で、「お前の設計はおかしい」って喧嘩してるスレッドじゃないか。面白すぎる lists.mysql.com/internals/38705
— SH2さん (@sh2nd) 2013年4月26日
さらにZardoshtがTokuDBの人だった RT @sh2nd: これKristianがMonty Program ABの人で、MatsがOracleの人で、「お前の設計はおかしい」って喧嘩してるスレッドじゃないか。面白すぎる lists.mysql.com/internals/38705
— SH2さん (@sh2nd) 2013年4月26日