MySQL内核技术之"Table结构与操作"

谈到Table,我们首先从SQL语句说起,因为围绕Table的所有操作都是由SQL触发的。设想一下,我们有如下SQL语句:

SELECT * FROM t1, t2 WHERE t1.a<10 AND t2.b < 20

这条语句涉及到两个table:t1 和 t2。在MySQL涉及到如下数据结构来操作上面SQL语句:

Table
TableList
TableCache
TableCacheManager

回到上面的SQL。语法解析后,query会带上一个成员变量TableList* table_list。TableList结构如下:

struct TABLE_LIST {
 ...
  Table* table;

  /* link in a global list of all queries tables */
  TABLE_LIST *next_global, **prev_global;
  const char *db, *table_name, *alias;
}
可以看到,TABLE_LIST结构实际上是list上的一个table节点(我觉得叫TABLE_LIST_NODE更加合适)。


当一个SQL被parse后成为lex结构,该结构就带了一个TABLE_LIST成员变量TableList* table_list。如果只有一个table的话,table_list就只有一个节点。对应的table_name和db都会被置上。但是table* 是为空的,因为初始状态table还没有被打开。


当SQL被优化阶段,会触发open_table()函数(位于sql_base.cc),会打开相应table:

/* make a new table */
if (!(table= (TABLE*) my_malloc(key_memory_TABLE,
sizeof(*table), MYF(MY_WME))))
goto err_lock;

error= open_table_from_share(thd, share, alias,
(uint) (HA_OPEN_KEYFILE |
HA_OPEN_RNDFILE |
HA_GET_INDEX |
HA_TRY_READ_ONLY),
EXTRA_RECORD,
thd->open_options, table, FALSE);
...
table->mdl_ticket= mdl_ticket;

table->next= thd->open_tables;	/* Link into simple list */
thd->set_open_tables(table);

table->reginfo.lock_type=TL_READ;	/* Assume read */

reset:
table->set_created();
/*
Check that there is no reference to a condition from an earlier query
(cf. Bug#58553). 
*/
DBUG_ASSERT(table->file->pushed_cond == NULL);
table_list->set_updatable(); // It is not derived table nor non-updatable VIEW
table_list->set_insertable();

table_list->table= table;
 
table->init(thd, table_list);

可以看到,table 被new 出来后被赋值到table_list的table中( table_list->table= table;)

通过这个过程,table被创建和赋值。但是上面这段代码之前,还有一处我们要注意:

Table_cache *tc= table_cache_manager.get_cache(thd);
/*
Try to get unused TABLE object or at least pointer to
TABLE_SHARE from the table cache.
*/
table= tc->get_table(thd, hash_value, key, key_length, &share);

上面的代码意思是先查看一下table cache里是否已经有了要用的table,如果有了,就直接拿出来,不用再new新的table了。这里涉及到了Table_cache:一个connection或者一个session对应了一个thd,thd又包含了一个Table_cache。当该thd发出SQL请求后,相应的Table被创建并缓存在Table_cache中,接下来该thd的SQL如果有访问同一个table,就不用再次创建了,直接去Table_cache中取即可。


这里要特别强调的是,在MySQL中,open_table是在optimize前面进行的,也就是操作的开始先open_table,再做其他优化操作。

你可能感兴趣的:(MySQL内核技术之"Table结构与操作")