浅析MySQL的Table_cache实现

由于本人水平有限,有错误的地方还请大家帮忙指正.
我们知道MySQL是一个插件式存储引擎的数据库,不同存储引擎的对象的元数据的存储方式是不一样的.例如:InnoDB的表的元数据信息都是存储在SYS_TABLES和SYS_INDEXES等数据字典中,数据结构也是dict_table_t 、dict_index_t等结构体,而MyISAM的表结构只有.frm文件存储.那么MySQL Server层怎样识别以及使用不同Engine的对象结构呢?

  • TABLE_SHARE
   MySQL Server层在缓存不同Engine的表对象过程中使用TABLE_SHARE的结构体,这里是不区分任何存储引擎的表结构,并且每一个表名(带模式名即库名)都一一对应一个TABLE_SHARE结构体对象.
TABLE_SHARE结构体主要成员如下:
struct TABLE_SHARE{ TABLE_CATEGORY table_category; //表的类型 ... Field **field; //表的field字段 KEY *key_info; //表定义的KEY信息(即索引信息) LEX_STRING table_cache_key; //TABLE_SHARE对象在table_cache中的key LEX_STRING db; //表所在的DB name LEX_STRING table_name; //表名 LEX_STRING path; //.frm文件路径名  // 指向每个table_cache包含该表的el地址 数组大小等于table_cache的数组大小  Table_cache_element **cache_element;  ...ulong   version;             //TABLE_SHARE的版本 如果版本变了 必须重新reopenulong mysql_version; /* 0 if .frm is created before 5.0 */ulong reclength; //记录长度ulong stored_rec_length; //存储的记录长度uint ref_count;              // TABLE 对象在使用的个数 即存在多少个TABLE对象 plugin_ref db_plugin; //存储引擎对象指针 ...}
当MySQL Server层在open table时,需要从frm文件(不区分存储引擎)中将这个表的表名、库名、所有的列信息、列的默认值、表的字符集、对应的.frm文件路径、所属的Engine、索引等信息存储到TABLE_SHARE结构体对象中,然后TABLE_SHARE对象在table_def_cache中缓存.(open_table_def中完成从frm到TABLE_SHARE写入)
  • TABLE
当我们获得TABLE_SHARE的对象之后,该如何使用TABLE_SHARE对象呢?同一时刻可能存在多个不同的session同时访问同一个表进行不同的操作,那么怎样保证每个不同的session的对象都是独立的互不影响的呢?
每个连接到MySQL Server层的thread在获得TABLE_SHARE对象之后(所有的线程可以共用一个TABLE_SHARE对象),都会创建一个TABLE结构体的对象,这个对象是该thread在使用期间独占的.(open_table_from_share )
TABLE结构体精简如下:
struct TABLE{TABLE_SHARE*s; //TABLE_SHARE对象指针handler*file; //存储引擎句柄 对存储引擎的操作通过该对象指针操作TABLE *next, *prev; //TABLE对象前后节点指针private:TABLE *cache_next, **cache_prev;//用于table_cache中的list链表节点指针friend class Table_cache_element; //用于访问cache_next和cache_prev两个成员public:THD*in_use;//thread 对象指针Field **field;//表的列的存储对象 同TABLE_SHARE中的列uchar *record[2];//记录数据的存储地址uchar *write_row_record;//THE::write_row中优化使用uchar *insert_values;//用于INSERT ... UPDATE....KEY*key_info;//表定义的KEY信息 同TABLE_SHARE....};
  • Table_cache管理
      MySQL Server层对TABLE对象的管理主要通过table_cache_manager完成,主要结构如下:
class Table_cache_element{// 缓存一个表名的所有TABLE对象 一个element对象只缓存一个表名的所有TABLEprivate:typedef I_P_List <TABLE,I_P_List_adapter<TABLE,&TABLE::cache_next,                                     &TABLE::cache_prev> > TABLE_list;  TABLE_list used_tables; // 正在使用的TABLE对象  TABLE_list free_tables; // 可以直接使用的TABLE 对象  TABLE_SHARE *share; // TABLE_SHARE 缓存对象  }  


推荐阅读