gdb backtrace

PageとかRecordとかの状態変化を観察するために色々logを出させて見たいのだけれども、コードを突っ込む場所としてはどこがいいのかあまり検討がつかない。logが出るタイミングにしても、こちらの意図したときに意図した範囲の内容が出るようにしたい。数日前にやってたha_innobase::openに突っ込むやり方は不細工過ぎる。

というわけでgdbを使っていろいろbacktraceを観察してみる。

InnoDBは関数名からの推測でbreakを突っ込むのが難しいので、ソースファイルと関数の命名規則が比較的シンプルなMyISAMにてまず確認し、Handlerレベルまでの経路をいろいろ見て当て感を良くしてから再度InnoDBに行きたい。

まずMyISAMに対するINSERT文の実行時。

#0  0x0838b786 in mi_write ()
#1  0x081d0802 in write_record ()
#2  0x081cfafc in mysql_insert ()
#3  0x08180170 in mysql_execute_command ()
#4  0x08186780 in mysql_parse ()
#5  0x0817c561 in dispatch_command ()
#6  0x0817c08d in do_command ()
#7  0x0817b602 in handle_one_connection ()
#8  0x4002ab63 in start_thread () from /lib/tls/libpthread.so.0
#9  0x4023418a in clone () from /lib/tls/libc.so.6

次が、MyISAMに対するUPDATE文の実行時。

#0  0x0838acc6 in mi_update ()
#1  0x081d9b29 in mysql_update ()
#2  0x0817eb65 in mysql_execute_command ()
#3  0x08186780 in mysql_parse ()
#4  0x0817c561 in dispatch_command ()
#5  0x0817c08d in do_command ()
#6  0x0817b602 in handle_one_connection ()
#7  0x4002ab63 in start_thread () from /lib/tls/libpthread.so.0
#8  0x4023418a in clone () from /lib/tls/libc.so.6

次が、MyISAMに対するDELETE文の実行時。

#0  0x0838e8e6 in mi_delete ()
#1  0x081dd036 in mysql_delete ()
#2  0x0817ee41 in mysql_execute_command ()
#3  0x08186780 in mysql_parse ()
#4  0x0817c561 in dispatch_command ()
#5  0x0817c08d in do_command ()
#6  0x0817b602 in handle_one_connection ()
#7  0x4002ab63 in start_thread () from /lib/tls/libpthread.so.0
#8  0x4023418a in clone () from /lib/tls/libc.so.6

固定長なMyISAMテーブルに対するFullScanなSELECT文の実行時。

#0  _mi_read_rnd_static_record ()
#1  0x083a1fb4 in mi_scan ()
#2  0x0823d443 in ha_myisam::rnd_next ()
#3  0x08230ae7 in rr_sequential ()
#4  0x081d3dc9 in sub_select ()
#5  0x081d38db in do_select ()
#6  0x081c4112 in JOIN::exec ()
#7  0x081c4579 in mysql_select ()
#8  0x081bf9d2 in handle_select ()
#9  0x08186ed1 in mysql_execute_command ()
#10 0x0818f882 in mysql_parse ()
#11 0x081851fa in dispatch_command ()
#12 0x08184ac8 in do_command ()
#13 0x08183c98 in handle_one_connection ()
#14 0x4002ab63 in start_thread () from /lib/tls/libpthread.so.0
#15 0x4023418a in clone () from /lib/tls/libc.so.6

なんというか、gdb便利すぎ。なんでこのツールをもっと早く使い出していなかったのかと小一時間凹む。数日前にmysql_execute_commandまで目視で呼び出し追跡した時にはそれだけで1時間以上かかってた。まあそれはそれでその過程で大量の付随コードを読むので意味がまったく無いというわけではない、と信じたいが。

ということで同じテーブルをalter tableでInnoDBにしたバージョン

#0  row_search_for_mysql ()
#1  0x08243941 in ha_innobase::index_read ()
#2  0x08243e70 in ha_innobase::index_first ()
#3  0x08244022 in ha_innobase::rnd_next ()
#4  0x08230ae7 in rr_sequential ()
#5  0x081d5012 in join_init_read_record ()
#6  0x081d3da6 in sub_select ()
#7  0x081d38db in do_select ()
#8  0x081c4112 in JOIN::exec  ()
#9  0x081c4579 in mysql_select ()
#10 0x081bf9d2 in handle_select ()
#11 0x08186ed1 in mysql_execute_command ()
#12 0x0818f882 in mysql_parse ()
#13 0x081851fa in dispatch_command ()
#14 0x08184ac8 in do_command ()
#15 0x08183c98 in handle_one_connection ()
#16 0x4002ab63 in start_thread () from /lib/tls/libpthread.so.0
#17 0x4023418a in clone () from /lib/tls/libc.so.6

でもって、以下はrow_search_for_mysqlの関数コメント。

Searches for rows in the database. This is used in the interface to
MySQL. This function opens a cursor, and also implements fetch next
and fetch prev. NOTE that if we do a search with a full key value
from a unique index (ROW_SEL_EXACT), then we will not store the cursor
position and fetch next or fetch prev must not be tried to the cursor!

ということらしいですよ。