MySQL のGDBによるデバッグ環境構築メモ
MySQL5.1からは、自作のストレージエンジンや自作の関数用のAPIが公開されている。
自作のストレージエンジンは気軽には作れないと思うが、自作の関数については検討の価値ありだと思う。
その際に役立つかもしれないデバッグ環境の構築メモ。
その前に、ここ の手順で、ソースを取得してデバッグオプション付きでMySQLをビルドしておく。
gdbでデバッグするには、下記のライブラリが「not stripped」でなければならない。そうじゃない場合は、glibcの再コンパイルが必要。CentOS5は「not stripped」なので問題ない。
# file -L /lib/libthread_db.so.1 /lib/libthread_db.so.1: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.9, not stripped # file -L /lib/libpthread.so.0 /lib/libpthread.so.0: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.9, not stripped
mysql-test ディレクトリに移動
# cd <MYSQLのソースディレクトリ>/mysql-test
テストケース作成
# vi t/example.test select 1;
テストケースexampleを実行
# ./mysql-test-run --record example Logging: ./mysql-test-run --record example 081006 21:26:45 [ERROR] Fatal error: Please read "Security" section of the manual to find out how to run mysqld as root! 081006 21:26:45 [ERROR] Aborting
というエラーが出てうまくいかなかった。どうやらmysqldの起動時にroot権限というのが問題らしい。
というわけで、mysqlユーザにて上記を再度やり直し。
# su - mysql
mysql-test ディレクトリに移動
$ cd /home/mysql/mysql-server/mysql-5.1/mysql-test
テストケース作成
$ vi t/example.test select 1; select now();
テスト実行
$ ./mysql-test-run --record example Logging: ./mysql-test-run --record example MySQL Version 5.1.30 Using dynamic switching of binlog format Skipping ndbcluster, mysqld not compiled with ndbcluster Skipping SSL, mysqld not compiled with SSL Using MTR_BUILD_THREAD = 0 Using MASTER_MYPORT = 9306 Using MASTER_MYPORT1 = 9307 Using SLAVE_MYPORT = 9308 Using SLAVE_MYPORT1 = 9309 Using SLAVE_MYPORT2 = 9310 Using IM_PORT = 9313 Using IM_MYSQLD1_PORT = 9314 Using IM_MYSQLD2_PORT = 9315 Killing Possible Leftover Processes Removing Stale Files Creating Directories Installing Master Database ======================================================= TEST RESULT TIME (ms) ------------------------------------------------------- main.example [ pass ] 2 ------------------------------------------------------- Stopping All Servers All 1 tests were successful. The servers were restarted 1 times Spent 0.002 of 3 seconds executing testcases
2つのテストケースが正常にpassしているのがわかる。
続いてgdbによるデバッグ ※要 X-Window、xterm (無い場合はWindows側にCygwinのXを入れて起動しておき、WindowsのX側でxhost + して、Linux側でexport DISPLAY=
$ ./mysql-test-run --gdb example
するとgdb が起動した状態の xterm が立ち上がりMySQLサーバーをgdbにてデバッグできる。
このexample.testが完了しても、デバッグウィンドウは開いたままになる。
このあと、mysqlクライアントで接続して任意のブレイクポイントを設定して、任意のクエリを実行してデバッグができる。
ちなみにこの時のサーバーのポートは9306で動作してる。
サーバーに接続して、クエリを実行する。
$ ../client/mysql -uroot -h127.0.0.1 --port=9306 test mysql> select 1;
デバッグウィンドウでは、ブレイクポイント mysql_parse() でちゃんと止まる。
Breakpoint 2, mysql_parse (thd=0x8919508, inBuf=0x8972930 "select 1", length=8, found_semicolon=0xb743b114) at sql_parse.cc:5655 5655 DBUG_ENTER("mysql_parse"); (gdb)
これで一通りデバッグ環境ができたので、自作関数などのテストが簡単になった。
- 主なブレークポイント設定場所リスト
操作 | おすすめブレークポイント |
SELECT | mysql_select() |
INSERT | mysql_insert() |
UPDATE | mysql_update() |
DELETE | mysql_delete() |
クエリキャッシュから答えが返っているかどうか | Query_cache::send_result_to_client() |
クライアントから通信パケットを読む | my_net_read() |
クライアントに通信パケットを書く | my_net_write() |
認証の接続 | check_connection() |
レプリケーションマスター側の更新ログ | MYSQL_LOG::write(Log_event *) |
レプリケーションスレーブの起動 | start_slave_threads() |
スレーブ上のネットワークI/Oを処理するレプリケーションスレッドの実行 | handle_slave_io() |
スレーブ上のSQLコマンドを処理するレプリケーションスレッドの実行 | handle_slave_sql() |
テーブルオープン | open_table() |
テーブル定義ファイル(.frm)の読み込み | openfrm() |
MyISAMテーブルのオープン | ha_myisam::open() |
InnoDBテーブルのオープン | ha_innobase::open() |
テーブルロックの取得 | mysql_lock_tables() |
トランザクションのコミット | ha_commit_trans() |