information_schema里的表每次select时新建?
起因:
InnoDB temporary table metadata is no longer stored to InnoDB system tables. Instead, a new table,INNODB_TEMP_TABLE_INFO, provides users with a snapshot of active temporary tables. The table contains metadata and reports on all user and system-created temporary tables that are active within a given InnoDBinstance. The table is created when the first SELECT statement is run against it.
innodb临时表的metadata不再存放在系统表,而是放在 INNODB_TEMP_TABLE_INFO, 这个表在每次select的时候建立。
mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> create temporary table tmp_a(id int);
Query OK, 0 rows affected (0.00 sec)
mysql> select now(), t.* from information_schema.tables t where table_name='innodb_temp_table_info'\G
*************************** 1. row ***************************
now(): 2016-11-25 17:24:27 --注意这个时间
TABLE_CATALOG: def
TABLE_SCHEMA: information_schema
TABLE_NAME: INNODB_TEMP_TABLE_INFO
TABLE_TYPE: SYSTEM VIEW
ENGINE: MEMORY
VERSION: 10
ROW_FORMAT: Fixed
TABLE_ROWS: NULL
AVG_ROW_LENGTH: 1011
DATA_LENGTH: 0
MAX_DATA_LENGTH: 16694643
INDEX_LENGTH: 0
DATA_FREE: 0
AUTO_INCREMENT: NULL
CREATE_TIME: 2016-11-25 17:24:27 --注意这个时间
UPDATE_TIME: NULL
CHECK_TIME: NULL
TABLE_COLLATION: utf8_general_ci
CHECKSUM: NULL
CREATE_OPTIONS: max_rows=16594
TABLE_COMMENT:
1 row in set (0.00 sec)
mysql> select now(), t.* from information_schema.tables t where table_name='innodb_temp_table_info'\G
*************************** 1. row ***************************
now(): 2016-11-25 17:24:31 --注意这个时间
TABLE_CATALOG: def
TABLE_SCHEMA: information_schema
TABLE_NAME: INNODB_TEMP_TABLE_INFO
TABLE_TYPE: SYSTEM VIEW
ENGINE: MEMORY
VERSION: 10
ROW_FORMAT: Fixed
TABLE_ROWS: NULL
AVG_ROW_LENGTH: 1011
DATA_LENGTH: 0
MAX_DATA_LENGTH: 16694643
INDEX_LENGTH: 0
DATA_FREE: 0
AUTO_INCREMENT: NULL
CREATE_TIME: 2016-11-25 17:24:31 --注意这个时间
UPDATE_TIME: NULL
CHECK_TIME: NULL
TABLE_COLLATION: utf8_general_ci
CHECKSUM: NULL
CREATE_OPTIONS: max_rows=16594
TABLE_COMMENT:
1 row in set (0.00 sec)
从上面的时间可以看出,每次查看的时候 ,create_time和当前时间是一致的,就是每次查看的时候会马上建立这个表。
mysql> select * from information_schema.innodb_temp_table_info;
+----------+--------------+--------+-------+----------------------+---------------+
| TABLE_ID | NAME | N_COLS | SPACE | PER_TABLE_TABLESPACE | IS_COMPRESSED |
+----------+--------------+--------+-------+----------------------+---------------+
| 43 | #sql7569_4_0 | 4 | 34 | FALSE | FALSE |
+----------+--------------+--------+-------+----------------------+---------------+
1 row in set (0.00 sec)
那么他后台是怎么走的呢?我试着打开general_log看看能不能看到一些操作,但是没有看到任何有用的信息。
只好看看代码:
--- 表的结构(或者说是字段信息) 如下
/* Fields of the dynamic table INNODB_TEMP_TABLE_INFO. */
static ST_FIELD_INFO i_s_innodb_temp_table_info_fields_info[] =
{
#define IDX_TEMP_TABLE_ID 0
{STRUCT_FLD(field_name, "TABLE_ID"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TEMP_TABLE_NAME 1
{STRUCT_FLD(field_name, "NAME"),
STRUCT_FLD(field_length, MAX_TABLE_UTF8_LEN),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TEMP_TABLE_N_COLS 2
{STRUCT_FLD(field_name, "N_COLS"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TEMP_TABLE_SPACE_ID 3
{STRUCT_FLD(field_name, "SPACE"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TEMP_TABLE_PTT 4
{STRUCT_FLD(field_name, "PER_TABLE_TABLESPACE"),
STRUCT_FLD(field_length, 64),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TEMP_TABLE_IS_COMPRESSED 5
{STRUCT_FLD(field_name, "IS_COMPRESSED"),
STRUCT_FLD(field_length, 64),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
END_OF_ST_FIELD_INFO
};
---填充表内容时实际执行
4220 /*******************************************************************//**
4221 Fill Information Schema table INNODB_TEMP_TABLE_INFO for a particular
4222 temp-table
4223 @return 0 on success, 1 on failure */
4224 static
4225 int
4226 i_s_innodb_temp_table_info_fill(
4227 /*=============================*/
4228 THD* thd, /*!< in: thread */
4229 TABLE_LIST* tables, /*!< in/out: tables
4230 to fill */
4231 const temp_table_info_t* info) /*!< in: temp-table
4232 information */
4233 {
4234 TABLE* table;
4235 Field** fields;
4236
4237 DBUG_ENTER("i_s_innodb_temp_table_info_fill");
4238
4239 table = tables->table;
4240
4241 fields = table->field;
4242
4243 OK(fields[IDX_TEMP_TABLE_ID]->store(info->m_table_id, true));
4244
4245 OK(field_store_string(
4246 fields[IDX_TEMP_TABLE_NAME], info->m_table_name));
4247
4248 OK(fields[IDX_TEMP_TABLE_N_COLS]->store(info->m_n_cols));
4249
4250 OK(fields[IDX_TEMP_TABLE_SPACE_ID]->store(info->m_space_id));
4251
4252 OK(field_store_string(
4253 fields[IDX_TEMP_TABLE_PTT], info->m_per_table_tablespace));
4254
4255 OK(field_store_string(
4256 fields[IDX_TEMP_TABLE_IS_COMPRESSED], info->m_is_compressed));
4257
4258 DBUG_RETURN(schema_table_store_record(thd, table));
4259 }
------------递归调用上面的 i_s_innodb_temp_table_info_fill
4298 /*******************************************************************//**
4299 This function will iterate over all available table and will fill
4300 stats for temp-tables to INNODB_TEMP_TABLE_INFO.
4301 @return 0 on success, 1 on failure */
4302 static
4303 int
4304 i_s_innodb_temp_table_info_fill_table(
4305 /*===================================*/
4306 THD* thd, /*!< in: thread */
4307 TABLE_LIST* tables, /*!< in/out: tables to fill */
4308 Item* ) /*!< in: condition (ignored) */
4309 {
4310 int status = 0;
4311 dict_table_t* table = NULL;
4312
4313 DBUG_ENTER("i_s_innodb_temp_table_info_fill_table");
4314
4315 /* Only allow the PROCESS privilege holder to access the stats */
4316 if (check_global_access(thd, PROCESS_ACL)) {
4317 DBUG_RETURN(0);
4318 }
4319
4320 /* First populate all temp-table info by acquiring dict_sys->mutex.
4321 Note: Scan is being done on NON-LRU list which mainly has system
4322 table entries and temp-table entries. This means 2 things: list
4323 is smaller so processing would be faster and most of the data
4324 is relevant */
4325 temp_table_info_cache_t all_temp_info_cache;
4326 all_temp_info_cache.reserve(UT_LIST_GET_LEN(dict_sys->table_non_LRU));
4327
4328 mutex_enter(&dict_sys->mutex);
4329 for (table = UT_LIST_GET_FIRST(dict_sys->table_non_LRU);
4330 table != NULL;
4331 table = UT_LIST_GET_NEXT(table_LRU, table)) {
4332
4333 if (!dict_table_is_temporary(table)) {
4334 continue;
4335 }
4336
4337 temp_table_info_t current_temp_table_info;
4338
4339 innodb_temp_table_populate_cache(
4340 table, ¤t_temp_table_info);
4341
4342 all_temp_info_cache.push_back(current_temp_table_info);
4343 }
4344 mutex_exit(&dict_sys->mutex);
4345
4346 /* Now populate the info to MySQL table */
4347 temp_table_info_cache_t::const_iterator end = all_temp_info_cache.end();
4348 for (temp_table_info_cache_t::const_iterator it
4349 = all_temp_info_cache.begin();
4350 it != end;
4351 it++) {
4352 status = i_s_innodb_temp_table_info_fill(thd, tables, &(*it)); ---通过这里递归
4353 if (status) {
4354 break;
4355 }
4356 }
4357
4358 DBUG_RETURN(status);
4359 }
------INNODB_TEMP_TABLE_INFO表的初始化
4361 /*******************************************************************//**
4362 Bind the dynamic table INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO.
4363 @return 0 on success, 1 on failure */
4364 static
4365 int
4366 i_s_innodb_temp_table_info_init(
4367 /*=============================*/
4368 void* p) /*!< in/out: table schema object */
4369 {
4370 ST_SCHEMA_TABLE* schema;
4371
4372 DBUG_ENTER("i_s_innodb_temp_table_info_init");
4373
4374 schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
4375
4376 schema->fields_info = i_s_innodb_temp_table_info_fields_info; --表结构
4377 schema->fill_table = i_s_innodb_temp_table_info_fill_table; --填充内容
4378
4379 DBUG_RETURN(0);
4380 }
他们四个之间的关系是:
表填充时的信息是从dict_sys->table_non_LRU里面得到的
dict_sys的定义如下:
1709 struct dict_sys_t{
1710 DictSysMutex mutex; /*!< mutex protecting the data
1711 dictionary; protects also the
1712 disk-based dictionary system tables;
1713 this mutex serializes CREATE TABLE
1714 and DROP TABLE, as well as reading
1715 the dictionary data for a table from
1716 system tables */
1717 row_id_t row_id; /*!< the next row id to assign;
1718 NOTE that at a checkpoint this
1719 must be written to the dict system
1720 header and flushed to a file; in
1721 recovery this must be derived from
1722 the log records */
1723 hash_table_t* table_hash; /*!< hash table of the tables, based
1724 on name */
1725 hash_table_t* table_id_hash; /*!< hash table of the tables, based
1726 on id */
1727 lint size; /*!< varying space in bytes occupied
1728 by the data dictionary table and
1729 index objects */
1730 dict_table_t* sys_tables; /*!< SYS_TABLES table */
1731 dict_table_t* sys_columns; /*!< SYS_COLUMNS table */
1732 dict_table_t* sys_indexes; /*!< SYS_INDEXES table */
1733 dict_table_t* sys_fields; /*!< SYS_FIELDS table */
1734 dict_table_t* sys_virtual; /*!< SYS_VIRTUAL table */
1735
1736 /*=============================*/
1737 UT_LIST_BASE_NODE_T(dict_table_t)
1738 table_LRU; /*!< List of tables that can be evicted
1739 from the cache */
1740 UT_LIST_BASE_NODE_T(dict_table_t)
1741 table_non_LRU; /*!< List of tables that can't be
1742 evicted from the cache */
1743 autoinc_map_t* autoinc_map; /*!< Map to store table id and autoinc
1744 when table is evicted */
1745 };
看到代码之后,发现information_schema里所有的表都应该是这样的
mysql> select now(), t.* from information_schema.tables t where table_name='tables'\G
*************************** 1. row ***************************
now(): 2016-11-25 17:35:43 --时间一致
TABLE_CATALOG: def
TABLE_SCHEMA: information_schema
TABLE_NAME: TABLES
TABLE_TYPE: SYSTEM VIEW
ENGINE: MEMORY
VERSION: 10
ROW_FORMAT: Fixed
TABLE_ROWS: NULL
AVG_ROW_LENGTH: 9441
DATA_LENGTH: 0
MAX_DATA_LENGTH: 16757775
INDEX_LENGTH: 0
DATA_FREE: 0
AUTO_INCREMENT: NULL
CREATE_TIME: 2016-11-25 17:35:43 --时间一致
UPDATE_TIME: NULL
CHECK_TIME: NULL
TABLE_COLLATION: utf8_general_ci
CHECKSUM: NULL
CREATE_OPTIONS: max_rows=1777
TABLE_COMMENT:
1 row in set (0.00 sec)
mysql>
mysql> select now(), t.* from information_schema.tables t where table_name='tables'\G
*************************** 1. row ***************************
now(): 2016-11-25 17:35:44 --时间一致
TABLE_CATALOG: def
TABLE_SCHEMA: information_schema
TABLE_NAME: TABLES
TABLE_TYPE: SYSTEM VIEW
ENGINE: MEMORY
VERSION: 10
ROW_FORMAT: Fixed
TABLE_ROWS: NULL
AVG_ROW_LENGTH: 9441
DATA_LENGTH: 0
MAX_DATA_LENGTH: 16757775
INDEX_LENGTH: 0
DATA_FREE: 0
AUTO_INCREMENT: NULL
CREATE_TIME: 2016-11-25 17:35:44 --时间一致
UPDATE_TIME: NULL
CHECK_TIME: NULL
TABLE_COLLATION: utf8_general_ci
CHECKSUM: NULL
CREATE_OPTIONS: max_rows=1777
TABLE_COMMENT:
1 row in set (0.00 sec)
QQ 273002188 欢迎一起学习
QQ 群 236941212
oracle,mysql,PG 相互交流