close_table

 参考

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

MySQL · 答疑解惑

 

 

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/

MySQL源码:JOIN顺序选择的复杂度

http://blog.csdn.net/wudongxu/article/details/6966052

mysql子查询(in)的实现

 

http://www.csdn.net/article/2015-01-16/2823591

MySQL · 性能优化· Group Commit优化

 

http://blog.csdn.net/wudongxu/article/details/6910057

MYSQL Order by的实现

 

http://blog.csdn.net/tonyxf121/article/details/7796657

mysql j

oin的实现原理及优化思路

 

mysql join

 

MySQL源码:索引相关的数据结构(后篇)

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

Innodb存储引擎查询分析

 

http://www.cnblogs.com/xpchild/p/3885640.html

nnodb物理存储结构系列2 行记录格式

 

 

http://ju.outofmemory.cn/entry/39281

 

http://www.orczhou.com/index.php/2012/12/mysql-source-code-optimizer-range-and-ref/

MySQL源码:Range和Ref优化的成本评估

 

 

MySQL源码:Range和Ref优化的成本评估

MySQL源代码:从SQL语句到MySQL内部对象

优之良品 生日礼物糖果礼盒女朋友礼物卡通糖果卡通啫喱糖48PS节日礼物

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;
}

 

你可能感兴趣的:(close_table)