2021年3月9日火曜日

MariaDB 10.5 の性能は不正?

普段は基本的にMariaDBの動向は全く追って無いです。 でも先日、MariaDB 10.5 のfsync()発行が少なく性能が良いのは何故なのかちょっと見てほしいと言われて、 mariadb-10.5.9.tar.gz をざっと見たらあっという間に原因特定。

「fsync()を待つべきなのに待ってないから」
只の不正と判明。

動作としては、
innodb_flush_log_at_trx_commit = 1
でも
innodb_flush_log_at_trx_commit = 2
でも
並列度が上がると多くのトランザクションが
innodb_flush_log_at_trx_commit = 0
の動作と同等となってしまうようです。

待たないのだから速いに決まってる。こんな不正なものと比較されるのは腹立たしいです。
指定のLSNまでのwriteやflushを終わらせる log_write_up_to() という関数があるのですが、 そこに下記のような assertion codeを入れて動かせば直ぐに落ちると思います。

mariadb-10.5.9> diff -up storage/innobase/log/log0log.cc.orig storage/innobase/log/log0log.cc
--- storage/innobase/log/log0log.cc.orig        2021-03-02 12:04:30.167590939 +0900
+++ storage/innobase/log/log0log.cc     2021-03-03 10:34:30.113416497 +0900
@@ -797,6 +797,8 @@ void log_write_up_to(lsn_t lsn, bool flu
   if (flush_to_disk &&
     flush_lock.acquire(lsn) != group_commit_lock::ACQUIRED)
   {
+    /* should be flushed enough */
+    ut_a(lsn <= log_sys.get_flushed_lsn());
     return;
   }

@@ -812,6 +814,9 @@ void log_write_up_to(lsn_t lsn, bool flu
     write_lock.release(write_lsn);
   }

+  /* should be written enough */
+  ut_a(lsn <= log_sys.write_lsn);
+
   if (!flush_to_disk)
   {
     return;
誰かの処理が「終わる」のを待つのではなく、 誰かがwrite/flushしてる「最中」であれば先に進んでしまう構造みたいです。

MariaDB 10.5 が速いなんて率先して言ってるベンチマークは怪しい意図を感じますね。

(追記)
log_write_up_to()はWAL(Write Ahead Log)の原則を守るためにデータページの書き出し前にも呼ばれます。これが破綻しているということは、ログを書く前にデータページを書く可能性があるということでクラッシュするとログを書いてるLSNまでも再現できずにデータが壊れる可能性があります。