tmp_table in THDオブジェクト

本題に戻る前に、友人から依頼されて1件、ソース解析ちゅう。

TEMPORARY TABLEに関する不具合の疑いについての調査。

とりあえずTHDを漁る。

(gdb) p sizeof(THD)
$2 = 5168

でかいよー。dddのData Windowに収まりきらん。

THD->tmp_tableってのがあるのだが、sql_class.hの1300行目付近

uint tmp_table;

とりあえずTHDにあるのはuintらしい。

(gdb) p thd->tmp_table
$4 = 0

初期値が0ってのは妥当なところ。

[test] > create temporary table foo (bar int);
Query OK, 0 rows affected (0.00 sec)

[test] > select * from foo;

temporary tableを作ってから再度アクセス。

(gdb) p thd->tmp_table
$5 = 1

ふーむ。

[test] > create temporary table foo2 (bar2 int);
Query OK, 0 rows affected (0.01 sec)

[test] > select * from foo;

もう1個作って見ると、

(gdb) p thd->tmp_table
$8 = 2

単にカウントアップされるだけっぽ。mysql_selectなんかにbを仕込んだおいらが悪かった模様。
次はがっつりmysql_execute_commandあたりからいくどー。 mysql_create_tableってのがあるじゃん。



はいはい、仕切り直しー。

初めて読む関数だからbtをおいておきまふ。

#1  0x0825eea8 in mysql_create_table (thd=0x8abdc50, db=0x8aa9970 "test",
    table_name=0x8adcf70 "foo3", create_info=0x8abe1d8, fields=@0x8abe0fc, keys=@0x8abe0f0,
    internal_tmp_table=false, select_field_count=0) at sql_table.cc:1569
#2  0x081a2a10 in mysql_execute_command (thd=0x8abdc50) at sql_parse.cc:2896
#3  0x081a9e80 in mysql_parse (thd=0x8abdc50,
    inBuf=0x8adcf10 "create temporary table foo3 (bar3 int)", length=38) at sql_parse.cc:5695
#4  0x081a00a6 in dispatch_command (command=COM_QUERY, thd=0x8abdc50,
    packet=0x8ad4ee1 "create temporary table foo3 (bar3 int)", packet_length=39) at sql_parse.cc:1736
#5  0x0819f8f0 in do_command (thd=0x8abdc50) at sql_parse.cc:1522
#6  0x0819ed25 in handle_one_connection (arg=0x8abdc50) at sql_parse.cc:1165
#7  0x4002ab63 in start_thread () from /lib/tls/libpthread.so.0
#8  0x4023418a in clone () from /lib/tls/libc.so.6

"create temporary table..."のときは、mysql_create_table関数の処理中に以下のifブロックに入るっ! sql_table.cc line1691.

if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
{
  /* Open table and put in temporary table list */
  if (!(open_temporary_table(thd, path, db, table_name, 1)))
  {
    (void) rm_temporary_table(create_info->db_type, path);
    goto end;
  }
  thd->tmp_table_used= 1;
}

THDへのアクセスきたよー。

TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
                const char *table_name, bool link_in_list)
{
  TABLE *tmp_table;
  ...
  if (link_in_list)
  {
    tmp_table->next=thd->temporary_tables;
    thd->temporary_tables=tmp_table;
    if (thd->slave_thread)
      slave_open_temp_tables++;
  }
  DBUG_RETURN(tmp_table);
}

link_in_listは値1がハードコーディングで渡されるので、ifブロックに必ず入るっ! でもってreplication slave以外は入れ子のifブロックにははいらな−い。

要はthd->temporary_tablesを見れということですな。でもって、各tmp_tableはLinkedList構造になっていると。

THDの基底クラスに*temporary_tablesがあったよー(><

class Open_tables_state
{
public:
  /*
    open_tables - list of regular tables in use by this thread
    temporary_tables - list of temp tables in use by this thread
    handler_tables - list of tables that were opened with HANDLER OPEN
     and are still in use by this thread
  */
  TABLE *open_tables, *temporary_tables, *handler_tables, *derived_tables;
  ...
}