:: DEVELOPER ZONE
MySQL バージョンはすべて、リリース前に多くのプラットフォームでテストされています。これは MySQL にバグがないというわけではありませんが、バグがあったとしても、非常に少なく見つけるのが困難です。何か問題がある場合に、システムをクラッシュさせているものを正確に調査することは、この問題の早期解決に役立ちます。
まず、問題は mysqld デーモンが死んでいることにあるのか、または問題がクライアントに関係しているのかを判断する必要があります。mysqladmin version を実行して、mysqld サーバが稼動していた時間を確認することができます。mysqld が死んでいる場合は、ファイル mysql-data-directory/`hostname`.err を見ることによりその原因を見つけることができます。 See 項4.10.1. 「エラーログ」。
システムの中には、このファイルに mysqld が死んだ際のスタックトレースがあるものがあり、resolve_back_stack で問題を解決できます。See 項E.1.4. 「スタックトレースの使用」。.err ファイルに書き込まれている変数値は、常に 100 パーセント正確であるとは限りません。
MySQL のクラッシュの多くは、インデックスファイルやデータファイルの破壊が原因です。
MySQL は、すべての SQL ステートメントの後で write() システムコールを呼び出し、ディスク上のデータを更新します。クライアントには、その後その結果が通知されます(delay_key_write で実行している場合で、データの書き込みだけの場合にはこの限りではありません)。
つまり、OS によってフラッシュされていないデータがディスクに確実に書き込まれるため、mysqld がクラッシュした場合でもデータは安全です。--flush を指定して mysqld を開始することによって、各 SQL コマンド実行後、強制的にすべてをディスクと同期させることができます。
つまり、以下のことがなければ、通常は破壊されたテーブルを得ることはありません。
誰かまたは何かが、更新中に mysqld またはマシンを強制終了した。
更新中に mysqld が死ぬようなバグを見つけた。
テーブルを適切にロックしないで、mysqld 外でデータまたはインデックスフファイルを操作している。
優れたファイルシステムロック(通常、lockd デーモンによって処理される)をサポートしていないシステム上で、同じデータに対して、多くの mysqld サーバを実行しているか、--skip-external-locking で複数サーバを実行している。
mysqld を混乱させるような不正なデータを含んだ、破損したインデックスまたはデータファイルがある。
データストレージのコードにバグを発見した。これはおそらくあり得ないことだが、可能性としてはある。この場合、修正されたテーブルのコピーに対して ALTER TABLE を使用して、ファイルタイプを別のデータストレージエンジンに変更することができる。
クラッシュの原因を見つけるのは非常に難しいので、まず、他で動作しているものが自分の環境でクラッシュするかどうかを確認してください。以下を試してください。
mysqladmin shutdown で mysqld デーモンを停止し、全テーブルで myisamchk --silent --force */*.MYI を実行した後、mysqld デーモンを再起動する。必ず、クリーンな状態から実行すること。 See 章 4. データベース管理。
mysqld --log を使用して、ログの情報から、特定のクエリがサーバを終了させるかどうかを判断する。バグの 95% が特定のクエリに関係している。通常、これは、MySQL 再実行直前のログファイルにある最後のクエリの 1 つである。 See 項4.10.2. 「一般クエリログ」。
クエリを実行する直前にすべてのテーブルを確認しても、クエリの 1 つで MySQL を何度も強制終了させることができる場合、バグを突き止められているので、バグレポートを発行する必要がある。
See 項1.7.1.3. 「バグまたは問題を報告する方法」。
問題の再現に使用するテストケースを作成する。 See 項E.1.6. 「テーブルが破損した場合にテストケースを作成する」。
組み込まれている mysql-test テストと MySQL ベンチマークを実行する。See 項13.1.2. 「MySQL テストスイート」。これによって MySQL を正確にテストできる。ベンチマークにアプリケーションをシミュレートするコードを追加することもできる。ベンチマークは、ソースディストリビューションまたはバイナリディストリビューションの bench ディレクトリか、MySQL インストールディレクトリの sql-bench ディレクトリにある。
fork_test.pl と fork2_test.pl を実行する。
デバッグ用に MySQL を設定している場合は、何か問題が発生した際に、考えられるエラー情報の収集が非常に容易になる。
configure に --with-debug オプションか --with-debug=full オプションを指定して MySQL を再設定し、その後再コンパイルする。
See 項E.1. 「MySQL サーバのデバッグ」。
デバッグ用に MySQL を設定すると、安全なメモリアロケータが組み込まれ、エラーを見つけることができる。また、何が発生しているかについて、多くの情報が提供される。
オペレーティングシステムの最新のパッチを適用しているかどうか確認する。
mysqld にオプション --skip-external-locking を指定する。システムの中には、lockd ロックマネージャが適切に動作しないものがある。--skip-external-locking オプションによって、mysqld に外部ロックを使用しないように指示することができる(つまり、同じデータで 2 つの mysqld サーバを実行することができない。myisamchk を使用する場合は注意が必要だが、テストとしてオプションを使用する場合は有益である)。
mysqld が動作しているように見えるのに応答がなかった時、mysqladmin -u root processlist を実行したか。mysqld は消滅しているように見えても、消滅していない場合がある。すべての接続が使用中であるか、内部ロック問題の可能性がある。
mysqladmin processlist は、通常、このような場合であっても接続を行うことができ、現在の接続数やその状況に関して有益な情報を取得できる。
他のクエリを実行中に、別のウィンドウで mysqladmin -i 5 status または mysqladmin -i 5 -r status を実行し、統計を生成する。
以下を実行してみる。
gdb から(または別のデバッガで)、mysqld を起動する。
See 項E.1.3. 「mysqld のデバッグ(gdb 使用)」。
テストスクリプトを実行する。
3つの最下位レベルで、バックトレースとローカル変数を出力する。gdb では、mysqld が gdb 内部でクラッシュした場合、以下のコマンドでこの出力を実行できる。
backtrace info local up info local up info local
gdb では、info threads により、存在しているスレッドを調べ、thread #(# はスレッド ID)で特定のスレッドにスイッチすることができる。
Perl スクリプトでアプリケーションをシミュレートし、MySQL をクラッシュさせたり不正な動作をさせたりする。
バグレポートを送付する。See 項1.7.1.3. 「バグまたは問題を報告する方法」。詳細なレポートにすること。MySQL は多くの人が使用しているため、クラッシュがあなたのコンピュータだけにある何らかの原因に起因している可能性がある(たとえば、特定のシステムライブラリに関連するエラー)。
可変長レコードを持つテーブルに問題があり、BLOB/TEXT カラム(BLOB/TEXT カラムのみ)を使用していない場合、ALTER TABLE で VARCHAR すべてを CHAR に変更することができる。これによって、MySQL は固定サイズのレコードを使用する。
固定サイズのレコードは余分な領域を少し取るだけだが、破壊に対して非常に大きな耐性がある。
現在の可変長レコードのコードは、少なくとも 3 年間は何の問題もなく MySQL AB で使用されてきた。しかし本来、可変長レコードはエラーが発生しやすく、上記のことが役立つかどうか試してみるのも有益である。
© 1995-2005 MySQL AB. All rights reserved.
