「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までも再現できずにデータが壊れる可能性があります。
That's old news, but seems, you were fast to jump to conclusions. If you were more curious during you little debugging experiment, you'd also dump the lsn value, to see it was a special value MAX_LSN. No lsn can be bigger than that. MariaDB used it in some contexts, where it meant "write lsn", but after a Japanese colleague brought your post to our attention. But anyway, thanks for testing and confirming MariaDB superiority in the flushing department. I always thought that "sophisticated" MySQL new redo log design, where 5 or so "dedicated" threads wait and signal each other, would not prove that great in practice, whereas a design that reduces wakes and sleeps, easily wins.
返信削除