🐬

MariaDBにコントリビュートする方法(非公式ガイド)

2021/01/02に公開

これは MySQL Advent Calendar 2020 の2日目の記事である。

MySQL についての記事を期待した方には申し訳ないが、MariaDB のコードベースの相当部分は MySQL と共通なので、MariaDB も MySQL の仲間ということで許してほしい。実際、テストやデバッグに関する記述は MySQL でも通用するはずだ。

はじめに

この記事の⽬的は、MariaDB の開発経験が無い者が初めて MariaDB にコントリビュートする際の指針を⽰すことにある。基本的なことは Contributing Code に書いてあるので、公式ドキュメントに書かれていない暗黙的な知識を記事の主眼とする。

MariaDB の内部構造について解説することはしない。Expert MySQL が参考になるのでそちらを見てほしい。また、Disk-oriented DB の一般論については、CMU の講義 がよい情報源になる。

※ この記事において、「コントリビュート」という語は、バグ修正や機能追加など実装を伴うもののみを指すものとする。なお、この記事は筆者の2020年11⽉時点での⾒解に基づいたものであり、将来に渡る正しさを保証しない。また、MariaDB Foundation の⾒解とは異なる記述を含む場合がある。

Issue の選び方

MariaDB は JIRA を issue tracker として使っている。まずは JIRA issue の中から適切なものを選んで取り組むのがよい。この節では、初⼼者がどのような issue を選ぶのがよいかについて、筆者の考えを述べる。

Issue にはいくつかタイプがあるが、最初はバグ修正から始めるのを勧めたい。機能追加やリファクタリングはゴールが明確でない場合が多く、最初に取り組むにはややハードルが高い。以下で issue と⾔った場合、常に type = bug の issue を指すものとする。

Contributing Code > Finding Development Projects to Work on には次のように書かれているが、このアドバイスには従わない方がよい

We are using JIRA to manage the MariaDB project. Go to https://jira.mariadb.org and click on "Projects" to get to the MariaDB project. Browse around the unresolved and unassigned issues to see if there is something that interests you.

Unresolved issue を選ぶのは当然である。そこに異論はない。が、unassigned issue は原則選ぶべきではない。何故なら⼀定以上重要 or 適切に起票されている issue が、unassigned のままで放置されることはほぼ無いからである。裏を返せば unassigned な issue は重要度が⾮常に低いか起票の仕⽅が悪いものが多く、これらは初⼼者には向かない。

よって初⼼者が取り組むべきは unresolved かつ assigned なタスクである。メーリングリストZulip で適切なタスクを提案してくれるように頼むか、assigned だが未着手の issue を勝手にやってしまうのがよいだろう。MariaDB のメンテナもそれでよいと言っている(Zulip を見るのが面倒な人のために下にキャプチャを貼る)。もちろん、他の⼈がすでに作業を開始している issue や、⼗分に議論が進んでおり着⼿⽬前のものを横取りするのは、明らかなマナー違反なので避けるべきである。

Zulipの会話

バグの再現

取り組む issue を決めたら、当該のバグを再現するテストを書く(繰り返すが issue と⾔った場合は常に type = bug のものを指す)。少なくとも最初のうちは、テストが書けない or 書き⽅がわからないようなバグには取り組むべきではない。

テストに先立って、MariaDB をビルドできるようにしよう。Ubuntu なら Building MariaDB on Ubuntu に従って依存パッケージをインストールし、例えば以下のようにコンパイルする。

mkdir build && cd $_
cmake -DCMAKE_BUILD_TYPE=Debug ..
cmake --build . --config Debug -j 8

E2E テストでバグを再現できるようにするとデバッグが捗る。MariaDB には独⾃の testing framework があるので、これを使う。例えば、既存のテストは下のようにして実⾏する。

cd build/mysql-test
./mtr --parallel=8

MariaDB のテストはコンポーネントや機能毎にいくつかの suite に分かれており、suite 毎、個々のテスト毎に実⾏することができる。

./mtr                     # すべてのテストを実⾏
./mtr innodb              # innodb suite のテストを実⾏
./mtr innodb.alter_table  # innodb suite の alter_table テストのみ実⾏
./mtr innodb --debug      # innodb suite のテストを debug mode で実⾏

新規にテストを作る場合は次のようにする。まず、適切な suite を選び、テストファイルと結果ファイルを作成する。

touch mysql-test/suite/${SUITE_NAME}/t/example.test
touch mysql-test/suite/${SUITE_NAME}/r/example.result

テストファイルにはSQL と test command が書ける。結果ファイルにはテストファイルに書いた SQL とその望ましい返り値を書く。以下に⾃明な例を挙げる。

example.test
--echo #
--echo # MDEV-XXXX issue title
--echo #
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1);
SELECT * FROM t1;
DROP TABLE t1;
--error ER_BAD_TABLE_ERROR
DROP TABLE t;
example.result
#
# MDEV-XXXX issue title
#
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1);
SELECT * FROM t1;
a
1
DROP TABLE t1;
DROP TABLE t;
ERROR 42S02: Unknown table 'test.t'

結果ファイルを手で書くのが面倒な場合は、テストファイルだけ書いて結果ファイルは空のままにする。この状態でテストを実⾏すると、実⾏結果が結果ファイルと同じディレクトリに example.reject という名前で生成されるので、それをベースにして結果ファイルを作る。

ややこしい作業は⼤抵 include file になっているので、悩んだら調べてみるとよい。--source include/have_innodb.inc のように書かれているのがそれである。テストファイルを書く前に⾊々試⾏錯誤したい場合は、./mtr --start-and-exit として、現在のバイナリでサーバーを起動するのがよい。

デバッグ

テストが書けたら、それを使ってどのコミットでバグが混⼊したか調べる。2分探索の要領でどの時点からテストが fail するようになるか調べればよい (git bisec を使うと楽だ)。原因となる commit が発⾒できたならラッキーだ。もう半分解決できたようなものである。

何らかの理由によりバグの原因となる変更を絞り込めなかった場合は、地道なデバッグを行う他ない。デバッグの手法について包括的に解説することはしない(できない)が、その代わりに筆者の「いつものやり方」をいくつか挙げておく。

  • --debug オプションを付けてテストを実⾏することで execution trace を⽣成し、どのあたりが怪しいか当たりをつける。その上で、必要に応じて gdb でデバッグしたりする。なお、execution trace は build/mysql-test/var/log/mysqld.1.trace に出力される。
  • エラーメッセージが出る場合、それに対応するエラー番号をコードから探し出し、その周辺を調べる。メッセージと番号の対応は sql/share/errmsg-utf8.txt を見ればわかる。
  • コードを読んでも何が行われているのかわからない場合、古いバージョン(例えば 5.5)まで戻って対応する箇所を読む。古いバージョンはコードが比較的単純で読みやすい。

うーむ、思ったよりもバラエティに乏しかった…。他に思いついたら追記する。

PR の作成

バグは解決できただろうか?できたなら Contributing Code > What to Expect From a MariaDB Server Developer を⼀読してから pull request を作成しよう。しばらくするとメンテナがレビュアーをアサインしてくれる。

PR を作成して1⽇たったら CI がすべて通っているか確認しよう。通っていなければ必要に応じて修正を⾏う。MariaDB の CI は遅く、混み合っている場合は本当に1日かかる😇

おわりに

半年前の自分(筆者)が読みたいと思うであろう内容をまとめたのが、この記事である。MariaDB のコードベースは複雑だが、バグを修正するだけであればそこまで難しくないので、興味がある人はぜひやってみてほしい。


2021/5/8 追記: MySQL/MariaDB のデバッグ方法について以下にまとめた。合わせて読んでもらえれば嬉しい。特に (2) と (3) は、MariaDB にコントリビュートする上でも参考になるはずだ。

Discussion