スマートスタイル TECH BLOG

データベース&クラウド技術情報

MySQLのコアファイルの出力について

MySQLのサポート業務では、(ユーザー視点では)突然 Signal 6Signal 11 をmysqldが受け取ってダウンするという問い合わせを頂く事が度々あります。

MySQLは数多くのバグフィックスや改善によって、頻繁にダウンすることはありません。
ちなみにGithub上のここ10年のCOMMIT数を数えてみると、77649 commitされていました。

それでも進化を続けているソフトウェアである以上、新しいプラグインや、新機能の影響、デグレ、またはハードウェア起因の問題によって、ダウンが発生することはあります。

今回は、ダウンが発生した際の原因調査に役立つコアファイルの出力方法についてご紹介します。

コアファイルとは

コアファイルとは、MANページに記載の通り、プロセスが保持していた仮想メモリ空間の情報をファイルに出力したものです。

https://man7.org/linux/man-pages/man5/core.5.html

The default action of certain signals is to cause a process to
terminate and produce a core dump file, a file containing an
image of the process’s memory at the time of termination. This
image can be used in a debugger (e.g., gdb(1)) to inspect the
state of the program at the time that it terminated. A list of
the signals which cause a process to dump core can be found in
signal(7).

ファイルサイズは、ps aux で確認した際の、VSZ の値以下になります(core_filterなどの影響により変動)。
試しに出力してみたところ、VSZは 1,778,140(KB) でしたが、コアファイルは 1,685,248(KB) でした。

コアファイルには、そのプログラムがシグナルを受けてダウンした瞬間のメモリ上の情報が含まれています。
つまり、mysqldのソースコードレベルで何の変数にどのような値を設定し、どのような関数を通ってダウンに至ったかといった情報をあとから確認することができます。

コアファイルの情報をもとに、C++のソースコードをデバッグするのは容易なことではありません。
しかし、何の機能に関連した問題だったのかということだけでもわかれば、回避策がわかるかもしれませんし、サポートへの調査依頼もスムーズになることでしょう。

MySQLでのコアファイルの出力準備

今回の環境は、CentOS 8 Streamを使用しています。

RHEL8系でのOSパラメータの調整

RHEL8系より、kernel.core_pettern=|/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h %e が設定されており、
コアファイルはデフォルトで /var/lib/systemd/coredump に出力されます。

また、デフォルトではコアファイルの出力サイズのソフトリミットが0となっているため、rootで起動しているアプリケーション以外ではコアファイルは出力できません。

今回はDefaultLimitCORE=infinity を設定し、コアファイルのサイズ上限を無限としています。
値は、=<soft>:<hard> の形式で指定ができます。
システム全体への影響を鑑みるとファイルサイズ制限をかけたくなりますが、中途半端に出力されたコアファイルは調査の役に立たないため、基本的にはinfinityとして、十分なサイズのある出力先を kernel.core_pattern に指定するというのがよいでしょう。

Linuxではsetuid()で起動ユーザを変えているアプリケーション(まさにmysqldではデフォルトでmysqlユーザをsetuidしています)からデフォルトでコアダンプできないようになっていますので、fs.suid_dumpable1 or 2 を指定します。
1 は単純にすべてのアプリケーションにコアダンプを許可するモードであり、2setuid() をしているアプリケーションのコアファイルのオーナーをrootにしてセキュアにするという設定です。
運用次第ですが、2 を設定するのが望ましいでしょう。

また、デフォルトではコアダンプに含まれる情報はフィルタされています。

ファイルサイズが増えますが、全ての情報を出力する設定にしたほうが後々有用な情報とはなります。

以上でOS側でコアファイルを出力する準備が整いました。

MySQLがコアファイルを出力するための準備

コアファイルの出力はmysqldではデフォルトでは無効です。

my.cnfcore_file パラメータを追加します。

mysqld_safeを使用している環境では以下も設定する必要があります。

また、別の環境にコアファイルを移してデバッグするというようなケースでは、コアファイルを出力したアプリケーションと、そのアプリケーションが利用していたすべてのライブラリ、及びデバッグシンボルも合わせて移す必要があります。

Percona社がそれらを簡単に収集するためのスクリプトを公開しておりますので、これを準備しておくのがよいでしょう。
使用方法は後述します。

最後に、RedHat系の一般的なソフトウェアバイナリでは開発時に設定していたデバッグ情報などを削除して軽量化したものを配布する事が多くあります。
※ なおel7 用の /usr/sbin/mysqld はデバッグ情報が埋め込まれたものが配布されています

例えば以下は、MySQLのデバッグシンボルパッケージをインストールしていない状態で取得した情報です。
MySQLには最低限のデバッグ情報は含まれており、関数名はわかるのである程度あたりがつきますが、処理までは確認することができません。

以下はデバッグシンボルパッケージをインストールした状態で取得したものです。
コードや行まで特定が可能になっています。
より具体的にバグを特定するにはこのような情報が必須になります

デバッグシンボルパッケージは、以下のようにインストールします。

コアファイル出力~解析用環境でコアファイルを読む

まずは、ともかくコアファイルを出力してみます。
デフォルトの出力先は、/var/lib/systemd/coredump です。

systemd-coredumpを使用している場合、lz4圧縮がかかるのでファイルサイズが10M程度で済んでいます。
とは言えGDBでこれを解析するには解凍が必要となりますが、 coredumpctl gdb コマンドを使用すると、そのままgdbでアタッチできたりします(とても便利!)
ですので、RHEL8系では必要以上にコアファイルサイズを恐れる必要が無くなっているようですね。

多くの情報とともに(gdb)のプロンプトが表示されます。
一旦quitして、必要なファイルを集めましょう。

[remote env] で指定した解析環境へログインし、ファイルを解凍すればOKです。

GDBでアタッチする

GDBでコアファイルにアタッチしてみましょう。
solib-search-path には収集したライブラリが格納されているディレクトリを指定します。

GDBには非常に多くのコマンドがありケースバイケースで使い分ける必要がありますが、mysqldが急に停止したという場合にまず確認したいのは、
停止時点で各スレッドがどの関数を実行していたかです。

info threads コマンドでスレッドの一覧と最後に実行していた関数名を確認することができます。
OSレベルから見たスレッドの一覧になりますので、親切にこれはInnoDBのスレッドですよ、というように明記されていません。

しかしながら、そのスレッドが実行している関数名からある程度の憶測ができます。
最後に実行した関数だけでは心もとない為、過去実行した関数も表示しましょう。
このようにスレッドが過去実行した関数の履歴をbacktrace(バックトレース)といいます。

バックトレースは、スレッドごとに確認することもできますが、ざっと全体を見渡したい場合は、すべてのスレッドにコマンドを実行することを意味するthread apply all を指定することになります。
backtraceの取得は、 backtrace もしくは bt ですので、以下のようなコマンドになります。

実行すると、例で言えば48スレッドが過去実行した関数名の流れが表示されるわけです。

以下のように出力があり、関数のどの行を実行して現在の状態に至っているか一目瞭然です。

まとめ

できればデータベースには安定して動いていてほしいものですが、急なダウンが発生した場合、大体はできるだけ早く原因追求して対処したいと考えるでしょう。

そのような場合に、ベンダ側での早期の解決をアシストするためにも、普段からデバッグ情報の出力準備をしておくことをオススメします。

次回(があれば)、さらにGDBコマンドでの解析についてご紹介したいと思います。

Let’s Enjoy MySQL!

Return Top