现在的位置: 首页 > 综合 > 正文

思考mysql内核之初级系列5—information_schema不是innodb数据字典

2014年02月12日 ⁄ 综合 ⁄ 共 5538字 ⁄ 字号 评论关闭

  上次谈到了innodb缓冲区里面有些页被使用了,这些中有些被数据字典用了。那么什么是数据字典呢?bingxialex继续思考。

 

1) information_schema不是innodb数据字典

   bingxi“alex,我觉得information_schema这个里面存储的不是数据字典,为了准确起见,换个说法,information_schema不是innodb数据字典。

   alex是的,innodb一直有数据字典的概念,而information_schema是在mysql5之后才出现的。因此,information_schema不是innodb数据字典。

   bingxi“alex,这样说有点牵强。我们首先举个例子吧。在手册里面,有这么一段话:

23.4. The INFORMATION_SCHEMA STATISTICS Table

The STATISTICS table provides information about table indexes.

  这段话表达的意思是:information_schema. statistics存储的是表索引信息。我们在test数据库下面建立一个表t1,并且在c1上有一个索引,语句如下:

create table test.t1

(

id int,

name varchar(20),

key it1id(id)

)engine=innodb;

接着我们查询statistics表中t1的索引信息:

mysql> select * from information_schema.statistics where table_name='t1' /G;

*************************** 1. row ***************************

TABLE_CATALOG: NULL

 TABLE_SCHEMA: test

   TABLE_NAME: t1

   NON_UNIQUE: 1

 INDEX_SCHEMA: test

   INDEX_NAME: it1id

 SEQ_IN_INDEX: 1

  COLUMN_NAME: id

    COLLATION: A

  CARDINALITY: 0

     SUB_PART: NULL

       PACKED: NULL

     NULLABLE: YES

   INDEX_TYPE: BTREE

      COMMENT:

1 row in set (0.02 sec)

 

ERROR:

No query specified

从中我们可以查到索引的信息,t1表真正只有一个索引么?呵呵,这里先卖个关子,在讲innodb数据字典的时候再说这个。现在我们聚焦在it1c1索引上,这些信息确实可以看到一些索引的信息,但是这个不是数据字典表,而仅仅只能供用户从外部查看使用,不能供mysql内核使用。比如,该索引在数据文件里面存储在什么地方?不知道根页信息,就没法去使用索引。我们再看看真正的innodb数据字典中包含的内容。(见文件D:/mysql-5.1.7-beta/storage/innobase/include/dict0mem.h

/* Data structure for an index */

struct dict_index_struct{

……

dict_table_t*   table;      //指向所属的table字典

ulint        space;        //索引所在的space

……

dict_tree_t*    tree;  //索引数结构

……

};

 

/* Data structure for an index tree */

struct dict_tree_struct{

……

ulint        space;      //索引所在的space

ulint        page;   //索引的根结点页号

……

};

  通过space,page我们就可以实实在在地在访问该索引。

  alex顶你,是这样的。通过show create我们还可以看出这些表是临时表。

mysql> show create table information_schema.tables /G;

*************************** 1. row ***************************

       Table: TABLES

Create Table: CREATE TEMPORARY TABLE `TABLES` (

  `TABLE_CATALOG` varchar(512) default NULL,

  ……

) ENGINE=MEMORY DEFAULT CHARSET=utf8

1 row in set (0.00 sec)

 

ERROR:

No query specified

  bingxi是的

 

2information_schema内容分析

  alex“bingxi,尽管information_schema不是innodb的数据字典,我们还是来摸索下information_schema对应的代码吧。主要的代码目录如下:

D:/mysql-5.1.7-beta/sql/sql_show.h

D:/mysql-5.1.7-beta/sql/sql_show.cpp

  bingxi“alex,从文件名我们可以看到show,是不是show status,show variables,show processlist等也是在这个文件里面执行。

  alex是的,没错。我们开始吧,先从两个数据结构开始。先看schema_tables数组。

ST_SCHEMA_TABLE schema_tables[]=

{

  {"CHARACTER_SETS", charsets_fields_info, create_schema_table,

   fill_schema_charsets, make_character_sets_old_format, 0, -1, -1, 0},

  ……

  {"STATUS", variables_fields_info, create_schema_table, fill_status,

   make_old_format, 0, -1, -1, 1},

  {"TABLES", tables_fields_info, create_schema_table,

   get_all_tables, make_old_format, get_schema_tables_record, 1, 2, 0},

  {"TABLE_CONSTRAINTS", table_constraints_fields_info, create_schema_table,

    get_all_tables, 0, get_schema_constraints_record, 3, 4, 0},

……

};

  数组有26个成员,而information_schema5.1.7版本中只有22个表。这是可以理解的,比如该数组里面有statusvariable,而这个在information_schema下是没有。我们通过show statusshow variables来执行。我们接着说这个数组的成员,每个成员是一个数组结构的取值,见下面的定义:

typedef struct st_schema_table

{

  const char* table_name;

  ST_FIELD_INFO *fields_info;

  TABLE *(*create_table)  (THD *thd, struct st_table_list *table_list);

  int (*fill_table) (THD *thd, struct st_table_list *tables, COND *cond);

  int (*old_format) (THD *thd, struct st_schema_table *schema_table);

  int (*process_table) (THD *thd, struct st_table_list *tables,

                        TABLE *table, bool res, const char *base_name,

                        const char *file_name);

  int idx_field1, idx_field2;

  bool hidden;

} ST_SCHEMA_TABLE;

  我们以tables这样表为例

 {"TABLES", tables_fields_info, create_schema_table,

   get_all_tables, make_old_format, get_schema_tables_record, 1, 2, 0},

  tables_fields_info表示的就是。

ST_FIELD_INFO tables_fields_info[]=

{

  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},

  {"TABLE_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},

  {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"},

  {"TABLE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},

  {"ENGINE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Engine"},

  {"VERSION", 21 , MYSQL_TYPE_LONG, 0, 1, "Version"},

  {"ROW_FORMAT", 10, MYSQL_TYPE_STRING, 0, 1, "Row_format"},

  {"TABLE_ROWS", 21 , MYSQL_TYPE_LONG, 0, 1, "Rows"},

  {"AVG_ROW_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Avg_row_length"},

  {"DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Data_length"},

  {"MAX_DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Max_data_length"},

  {"INDEX_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Index_length"},

  {"DATA_FREE", 21 , MYSQL_TYPE_LONG, 0, 1, "Data_free"},

  {"AUTO_INCREMENT", 21 , MYSQL_TYPE_LONG, 0, 1, "Auto_increment"},

  {"CREATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Create_time"},

  {"UPDATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Update_time"},

  {"CHECK_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Check_time"},

  {"TABLE_COLLATION", 64, MYSQL_TYPE_STRING, 0, 1, "Collation"},

  {"CHECKSUM", 21 , MYSQL_TYPE_LONG, 0, 1, "Checksum"},

  {"CREATE_OPTIONS", 255, MYSQL_TYPE_STRING, 0, 1, "Create_options"},

  {"TABLE_COMMENT", 80, MYSQL_TYPE_STRING, 0, 0, "Comment"},

  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}

};

  这个表示的就是tables表的字段,不考虑这行’ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}’,对比下desc tables;两边是一样的。

  Bingxi我顶你,我们通过一个例子来看吧,以show status为例

  {"STATUS", variables_fields_info, create_schema_table, fill_status,

   make_old_format, 0, -1, -1, 1},

//根据对比,我们可以知道:

// create_schema_table的功能是:TABLE *(*create_table)

// fill_status的功能是:int (*fill_table)

// make_old_format的功能是:int (*old_format),这个可以暂时不调试

  首先我们查看函数mysql_schema_table,在其中调用了函数create_schema_table

int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list)

{

  ……

  // table_list->schema_table对应的结构就是st_schema_table

  //对应的值为:{"STATUS", variables_fields_info, create_schema_table, fill_status,

  // make_old_format, 0, -1, -1, 1},

  //因此这里的create_table等于访问create_schema_table

  if (!(table= table_list->schema_table->create_table(thd, table_list)))

  {

    DBUG_RETURN(1);

  }

抱歉!评论已关闭.