参考
http://www.tocker.ca/2014/07/30/beyond-the-frm-ideas-for-a-native-mysql-data-dictionary.html
http://mysql.taobao.org/monthly/2015/08/07/
http://blog.sina.com.cn/s/blog_4673e60301010r5u.html
http://m.blog.chinaunix.net/uid-28364803-id-3410671.html
http://m.blog.chinaunix.net/uid-26896862-id-3329896.html
http://www.cnblogs.com/xpchild/p/3780625.html
http://ikarishinjieva.github.io/tachikoma-blog/
http://blog.jobbole.com/87137/
http://whuai.blog.51cto.com/3539000/862197
http://www.mysqlab.net/blog/2010/09/mysql-lock-management/
ALTER TABLE例子
http://www.kancloud.cn/taobaomysql/monthly/67076
http://www.dedecms.com/knowledge/data-base/mysql/2012/0813/4568.html
http://www.orczhou.com/index.php/2012/12/mysql-join-order-complex-or-not/
http://blog.csdn.net/wudongxu/article/details/6966052
mysql子查询(in)的实现
http://blog.csdn.net/wudongxu/article/details/6910057
MYSQL Order by的实现
http://blog.csdn.net/tonyxf121/article/details/7796657
mysql j
oin的实现原理及优化思路
mysql join
http://www.orczhou.com/index.php/2012/11/mysql-source-code-how-mysql-find-usable-index/
http://database.51cto.com/art/201303/383042.htm
http://www.dedecms.com/knowledge/data-base/mysql/2012/0813/4568.html
http://www.cnblogs.com/xpchild/p/3885640.html
http://ju.outofmemory.cn/entry/39281
http://www.orczhou.com/index.php/2012/12/mysql-source-code-optimizer-range-and-ref/
TABLE *unused_tables; //table share实例化的对象table 所在的lru
HASH table_def_cache;
static TABLE_SHARE *oldest_unused_share, end_of_unused_share;
释放table_share时采用lru,是因为只通过 装载table_share的hashTable是无法定位哪一个table_share是属于lru特征的
TABLE_SHARE的释放采用LRU顺序,由oldest_unused_share,end_of_unused_share这两个链表指针控制实现:空闲的SHARE是插入到end_of_unused_share之前,即尾插法,而释放时是从链表的头部oldest_unused_share开始的,代码详见release_table_share和table_def_init函数
空闲TABLE实例的释放也采用LRU顺序,TABLE空闲时被移到unused_tables中是插在链表的尾部,释放时也是从unused_tales头部开始,整个unused_tables是一个环形的双链表,代码详见close_thread_table和free_cache_entry函数
case SQLCOM_ALTER_PROCEDURE:
case SQLCOM_ALTER_FUNCTION:
close_thread_tables(thd);
close_open_tables
close_thread_table
void close_mysql_tables(THD *thd) { /* No need to commit/rollback statement transaction, it's not started. */ DBUG_ASSERT(thd->transaction.stmt.is_empty()); close_thread_tables(thd); thd->mdl_context.release_transactional_locks(); }
/* move one table to free list */ /**
*
*#define TABLE_OPEN_CACHE_DEFAULT 400
*#define TABLE_DEF_CACHE_DEFAULT 400
*
*将实例对象table 放在unused_table的prev结点
*如果实例对象个数超过table_cache_size,从全局变量unused_table中删除掉
*
*先通过table找到table_share,再调用table_share中的used_tables这个对象的remove方法
*table->s->used_tables.remove(table)
*table->s->free_tables.push_front(table)
*再将table置为unused_tables这个(全部变量)链表的头结点
*
*如果所有table实例的个数大于400,就循环删除全部链表unused_tables的头结点
*找到头结点,判断该table->in_use是否为0
*如果不为0,执行 table->s->used_tables.remove(table)
*如果为0,执行table->s->free_tables.remove(table),同时
*/ bool close_thread_table(THD *thd, TABLE **table_ptr) { bool found_old_table= 0; TABLE *table= *table_ptr; DBUG_ENTER("close_thread_table"); DBUG_ASSERT(table->key_read == 0); *table_ptr=table->next; if (table->s->has_old_version() || table->needs_reopen() || table_def_shutdown_in_progress) { free_cache_entry(table); found_old_table= 1; } else { DBUG_ASSERT(table->file); table_def_unuse_table(table); /* We free the least used table, not the subject table, to keep the LRU order. */ if (table_cache_count > table_cache_size) free_cache_entry(unused_tables); } mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(found_old_table); }
将实例对象table 放在unused_table的prev结点
/** Mark already existing used TABLE instance as unused. */ static void table_def_unuse_table(TABLE *table) { DBUG_ASSERT(table->in_use); /* We shouldn't put the table to 'unused' list if the share is old. */ DBUG_ASSERT(! table->s->has_old_version()); table->in_use= 0; /* Remove table from the list of tables used in this share. */ table->s->used_tables.remove(table); /* Add table to the list of unused TABLE objects for this share. */ table->s->free_tables.push_front(table); /* Also link it last in the global list of unused TABLE objects. */ if (unused_tables) { table->next=unused_tables; table->prev=unused_tables->prev; unused_tables->prev=table; table->prev->next=table; } else unused_tables=table->next=table->prev=table; check_unused(); }
/**
*这个参数 TABLE *table 其实是unused_tables,它是个全局变量,里面全是table_share的实例table
*找到table的成员变量s,再使用s的成员方法free_tables的remove方法,移除当前table
*同时unused_tables移除第一个table
*/
static void free_cache_entry(TABLE *table) { DBUG_ENTER("free_cache_entry"); /* This should be done before releasing table share. */ table_def_remove_table(table); intern_close_table(table); my_free(table); DBUG_VOID_RETURN; }
/** Prepare used or unused TABLE instance for destruction by removing it from share's and global list. */ /**
*从table的used_tables或者free_tables链表中删除
*将全局unused_tables中删除
*
*/ static void table_def_remove_table(TABLE *table) { if (table->in_use) { /* Remove from per-share chain of used TABLE objects. */ table->s->used_tables.remove(table); } else { /* Remove from per-share chain of unused TABLE objects. */ table->s->free_tables.remove(table); /* And global unused chain. */ table->next->prev=table->prev; table->prev->next=table->next; if (table == unused_tables) { unused_tables=unused_tables->next; if (table == unused_tables) unused_tables=0; } check_unused(); } table_cache_count--; }
void intern_close_table(TABLE *table) { // Free all structures DBUG_ENTER("intern_close_table"); DBUG_PRINT("tcache", ("table: '%s'.'%s' 0x%lx", table->s ? table->s->db.str : "?", table->s ? table->s->table_name.str : "?", (long) table)); free_io_cache(table); delete table->triggers; if (table->file) // Not true if placeholder (void) closefrm(table, 1); // close file DBUG_VOID_RETURN; }
/* Free information allocated by openfrm SYNOPSIS closefrm() table TABLE object to free free_share Is 1 if we also want to free table_share */ int closefrm(register TABLE *table, bool free_share) { int error=0; DBUG_ENTER("closefrm"); DBUG_PRINT("enter", ("table: 0x%lx", (long) table)); if (table->db_stat) error=table->file->close(); my_free((void *) table->alias); table->alias= 0; if (table->field) { for (Field **ptr=table->field ; *ptr ; ptr++) delete *ptr; table->field= 0; } delete table->file; table->file= 0; /* For easier errorchecking */ #ifdef WITH_PARTITION_STORAGE_ENGINE if (table->part_info) { free_items(table->part_info->item_free_list); table->part_info->item_free_list= 0; table->part_info= 0; } #endif if (free_share) { if (table->s->tmp_table == NO_TMP_TABLE) release_table_share(table->s); else free_table_share(table->s); } free_root(&table->mem_root, MYF(0)); DBUG_RETURN(error); }
/** Mark that we are not using table share anymore. @param share Table share If the share has no open tables and (we have done a refresh or if we have already too many open table shares) then delete the definition. */ void release_table_share(TABLE_SHARE *share) { DBUG_ENTER("release_table_share"); DBUG_PRINT("enter", ("share: 0x%lx table: %s.%s ref_count: %u version: %lu", (ulong) share, share->db.str, share->table_name.str, share->ref_count, share->version)); mysql_mutex_assert_owner(&LOCK_open); DBUG_ASSERT(share->ref_count); if (!--share->ref_count) { if (share->has_old_version() || table_def_shutdown_in_progress) my_hash_delete(&table_def_cache, (uchar*) share); else { /* Link share last in used_table_share list */ DBUG_PRINT("info",("moving share to unused list")); DBUG_ASSERT(share->next == 0); share->prev= end_of_unused_share.prev; *end_of_unused_share.prev= share; end_of_unused_share.prev= &share->next; share->next= &end_of_unused_share; if (table_def_cache.records > table_def_size) { /* Delete the least used share to preserve LRU order. */ my_hash_delete(&table_def_cache, (uchar*) oldest_unused_share); } } } DBUG_VOID_RETURN; }