起動プロセス(1) mainからinnobase_initまで

というわけで、InnoDBの起動プロセスの説明を試みるエントリの連載を開始しちゃいます!!!11

本当にちゃんと説明できるかどうかの責任はもちませんw 解釈間違いがあるかもしれませんw ということをお断りしつつ、れっつすたあと。

対象バージョンは、5.0.24です。



mysqldがmain関数より起動すると、init_server_components関数が呼ばれる。この中でさらにha_init関数が呼び出される。

ha_init関数では、sys_table_types配列に含まれるhandlertonに対して、それぞれinit関数を呼び出していく。

for (types= sys_table_types; *types; types++)
{
  if (!(*types)->init || !(*types)->init())
    ha_was_inited_ok(types);
  else
    (*types)->state= SHOW_OPTION_DISABLED;
}

このsys_table_types配列は以下のように初期化されており、

handlerton *sys_table_types[]=
{
  &myisam_hton,
  &heap_hton,
  &innobase_hton,
  &berkeley_hton,
  &blackhole_hton,
  &example_hton,
  &archive_hton,
  &tina_hton,
  &ndbcluster_hton,
  &federated_hton,
  &myisammrg_hton,
  &binlog_hton,
  &isam_hton,
  NULL
};

handlerton構造体の配列となっている。ここでinnobase_htonが格納されているため、InnoDBも初期化の対象となっている。

ちなみにhandlertonとは、mysqldにつき1インスタンスのみ生成されるもので、各テーブルごとには作成されない。各テーブルに対しては別のhandlerインスタンスが生成されるものと思われる。

handlertonの定義は以下となっている。

typedef struct
{
  const char *name;
  SHOW_COMP_OPTION state;
  const char *comment;
  enum db_type db_type;
  bool (*init)();
  uint slot;
  uint savepoint_offset;
  int  (*close_connection)(THD *thd);
  int  (*savepoint_set)(THD *thd, void *sv);
  int  (*savepoint_rollback)(THD *thd, void *sv);
  int  (*savepoint_release)(THD *thd, void *sv);
  int  (*commit)(THD *thd, bool all);
  int  (*rollback)(THD *thd, bool all);
  int  (*prepare)(THD *thd, bool all);
  int  (*recover)(XID *xid_list, uint len);
  int  (*commit_by_xid)(XID *xid);
  int  (*rollback_by_xid)(XID *xid);
  void *(*create_cursor_read_view)();
  void (*set_cursor_read_view)(void *);
  void (*close_cursor_read_view)(void *);
  uint32 flags;                                /* global handler flags */
} handlerton;

先ほどのha_init関数の中では、handlerton->init関数ポインタへの呼び出しが行われていた。InnoDBではinnobase_htonを以下のように実装しているため、この呼び出し時にはinnobase_init関数が呼び出されることになる。

handlerton innobase_hton = {
  "InnoDB",
  SHOW_OPTION_YES,
  "Supports transactions, row-level locking, and foreign keys",
  DB_TYPE_INNODB,
  innobase_init,
  0,				/* slot */
  sizeof(trx_named_savept_t),	/* savepoint size. TODO: use it */
  innobase_close_connection,
  innobase_savepoint,
  innobase_rollback_to_savepoint,
  innobase_release_savepoint,
  innobase_commit,		/* commit */
  innobase_rollback,		/* rollback */
  innobase_xa_prepare,		/* prepare */
  innobase_xa_recover,		/* recover */
  innobase_commit_by_xid,	/* commit_by_xid */
  innobase_rollback_by_xid,     /* rollback_by_xid */
  innobase_create_cursor_view,
  innobase_set_cursor_view,
  innobase_close_cursor_view,
  HTON_NO_FLAGS
};

このときのbacktraceを以下に記しておく。

#0  innobase_init () at ha_innodb.cc:1214
#1  0x08257140 in ha_init () at handler.cc:485
#2  0x08192a2a in init_server_components () at mysqld.cc:3099
#3  0x08193314 in main (argc=1, argv=0xbfad71b4) at mysqld.cc:3425