Debugging MySQL/MariaDB (4): Debugging with rr
重い腰を上げて Debugging MySQL/MariaDB シリーズの第4弾を書いている。今回は rr debugger を使用したデバッグについて説明する。Intel または AMD の CPU を搭載した物理マシンに Linux (kernel 3.11+) をネイティブインストールした環境を前提とする。
rr debugger
rr は Pernoscoによって開発されているデバッガーである。rr は gdb と同じ感覚で使えるが、次に挙げる gdb にはないすばらしい特徴を備えている。
- プログラムの実行を記録し、バグを何度でも決定的に再現することができる。
- ブレークポイントやウォッチポイントまで逆実行 (reverse execution) できる。
これらの特徴の何がすばらしいのか?想像してほしい。散発的なバグ(再現したりしなかったりするバグ)を GDB でデバッグするのは苦痛である。ハズレの実行を引いてしまった場合、すべてが無駄になる。また、散発的でないバグであっても、手が滑って調べたい箇所を過ぎてしまうということはよくある。あるいは、ある値がどこで変数にセットされたか調べたいと思ったことはないだろうか?rr を使えば、これらの問題をすべて解決することができるのである。
Install rr
rr の公式ページ の説明にしたがって rr をインストールしよう。もし、比較的新しい CPU を使っているなら、ソースからビルドしてインストールするのを勧める。リリース版の rr が、その CPU のマイクロアーキテクチャを識別できない可能性があるためである。
Hardware/software configuration > OS configuration にしたがって OS の設定を変更する。AMD Ryzen を使っている場合は、更に こちらの設定 を施す必要がある。
Debug MariaDB with rr
まずデバッグビルドする。※ Performance schema と debug trace が有効だと、rr と組合せたときに遅くなるので無効にしているが、有効だと rr が使えないわけではない。
mkdir bld && cd $_ cmake .. -DCMAKE_BUILD_TYPE=Debug -DPLUGIN_PERFSCHEMA=NO -DWITH_DBUG_TRACE=OFF cmake --build . --config Debug -j 8
デバッグしたいテストケースを指定して、--rr
オプション付きで MTR を実行する。
./mysql-test/mtr innodb.alter_table --rr
すると rr のトレースファイルが生成され、今回の実行を何度でもデバッグできるようになる。rr replay
でトレースを再生できる。
rr replay ./mysql-test/var/log/mysqld.1.rr/latest-trace
> rr replay ./mysql-test/var/log/mysqld.1.rr/latest-trace ... (rr) b dispatch_command Breakpoint 1 at 0x55f844a57dc6: file /home/nayuta_mariadb/repo/mariadb-server/10.9/sql/sql_parse.cc, line 1595. (rr) c ... Thread 2 hit Breakpoint 1, dispatch_command (command=COM_QUERY, thd=0x7f8c64001ba8, packet=0x7f8c6400c589 "SHOW SLAVE STATUS", packet_length=17, blocking=true) at /home/nayuta_mariadb/repo/mariadb-server/10.9/sql/sql_parse.cc:1595 1595 { (rr) n 1596 NET *net= &thd->net; (rr) n 1597 bool error= 0; (rr) n 1598 bool do_end_of_statement= true; (rr) n 1600 DBUG_PRINT("info", ("command: %d %s", command, (rr) n 1604 bool drop_more_results= 0; (rr) rn 1600 DBUG_PRINT("info", ("command: %d %s", command, (rr) watch error Hardware watchpoint 2: error (rr) rc Continuing. Thread 2 hit Hardware watchpoint 2: error Old value = false New value = 85 dispatch_command (command=COM_QUERY, thd=0x7f8c64001ba8, packet=0x7f8c6400c589 "SHOW SLAVE STATUS", packet_length=17, blocking=true) at /home/nayuta_mariadb/repo/mariadb-server/10.9/sql/sql_parse.cc:1597 1597 bool error= 0
上の実行例からわかるように、rn
(reverse-next
) で1ステップ戻ることができ、rc
(reverse-continue
) で逆向きに continue
することができる。watch
等も gdb と同様に機能する。この便利さがわかるだろうか?私の説明で便利さが伝わなかったとしても、騙されたと思って一度使ってみてほしい。デバッグの効率が数倍上がるはずだ。
Debug MySQL with rr
私の知る限り MySQL の MTR は --rr
オプションをサポートしていないが、次のようにしてトレースを生成することができる。
(まだ書いてない)