MySQL 记录、页、索引的数据结构简析( 三 )

  • Adaptive Hash Index(自适应哈希索引,简称 AHI),根据热点行记录进行索引,但是如果记录发生变化,也需要维护自适应哈希索引 。
  • 数据结构B-tree cursor 对应 btr_cur_t 结构体 。
    /** The tree cursor: the definition Appears here only for the compilerto know struct size! */struct btr_cur_t { btr_cur_t() { memset(this, 0, sizeof(*this)); } dict_index_t* index;/*!< index where positioned */ page_cur_t page_cur; /*!< page cursor */ purge_node_t* purge_node; /*!< purge node, for BTR_DELETE */ buf_block_t* left_block; /*!< this field is used to storea pointer to the left neighborpage, in the casesBTR_SEARCH_PREV andBTR_MODIFY_PREV */ /*------------------------------*/ que_thr_t* thr;/*!< this field is only usedwhen btr_cur_search_to_nth_levelis called for an index entryinsertion: the calling querythread is passed here to beused in the insert buffer */ /*------------------------------*/};其中:
    • page_cur_t page_cur,保存 page cursor。
    page cursor 对应 page_cur_t 结构体 。
    /** Index page cursor */struct page_cur_t{ const dict_index_t* index; rec_t*rec; /*!< pointer to a record on page */ ulint*offsets; buf_block_t* block; /*!< pointer to the block containing rec */};其中:
    • rec_t* rec,表示游标查询得到的记录;
    • buf_block_t* block,表示表示游标查询得到的记录所在块信息 。
    persistent cursor 对应 btr_pcur_t 数据结构 。
    /* The persistent B-tree cursor structure. This is used mainly for SQLselects, updates, and deletes. */struct btr_pcur_t{ btr_pcur_t() { memset(this, 0, sizeof(*this)); } /** a B-tree cursor */ btr_cur_t btr_cur;rec_t*old_rec;/** Return the index of this persistent cursor */ dict_index_t* index() const { return(btr_cur.index); }};其中:
    • rec_t* old_rec,持久化游标中保存查询得到的记录 。
    下面以 insert 语句的执行为例,分析不同数据结构之间的关系 。
    insert 语句build_template从 server 层调用存储引擎的接口 handler 开始,具体是 ha_innobase::write_row 函数 。
    // storage/innbase/handler/ha_innodb.cc/* Stores a row in an InnoDB database, to the table specified in this handle. */intha_innobase::write_row(/*===================*/ uchar* record) /*!< in: a row in MySQL format */{/* Step-4: Prepare INSERT graph that will be executed for actual INSERT (This is a one time operation) */ if (m_prebuilt->mysql_template == NULL|| m_prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {/* Build the template used in converting quickly betweenthe two database formats */build_template(true); }/* Step-5: Execute insert graph that will result in actual insert. */ // 插入数据 error = row_insert_for_mysql((byte*) record, m_prebuilt);}其中:
    • 入参 uchar* record 指向 table->record[0],其中不包含表列的类型、列的长度、列数等信息 , 完全是客户端插入的数据;
    unsigned char 数据类型经常被用于处理原始字节数据,比如在进行二进制文件读写、网络通信、处理图像数据、编码转换或者其他需要以字节为单位操作的场景中 。利用 unsigned char 可以确保不会有负值出现,这在与二进制数据和位操作打交道时非常有用 。
    • 调用 build_template 函数初始化 m_prebuilt 变量;
    • 调用 row_insert_for_mysql 函数插入数据,入参中将 record 指针从 uchar 转换成 byte 类型 。
    typedef unsigned char uchar; /* Short for unsigned char *//* Note that inside MySQL 'byte' is defined as char on linux! */#define byteunsigned charm_prebuilt 变量是 row_prebuilt_t 结构体指针类型,其中部分成员如下所示,包括表、索引、游标等各种信息 。
    /** Save CPU time with prebuilt/cached data structures */row_prebuilt_t*m_prebuilt;/** A struct for (sometimes lazily) prebuilt structures in an Innobase tablehandle used within MySQL; these are used to save CPU time. */struct row_prebuilt_t { dict_table_t* table;/*!< Innobase table handle */ dict_index_t* index;/*!< current index for a search, if any */ trx_t*trx;/*!< current transaction handle */unsigned n_template:10; /*!< number of elements in thetemplate */ins_node_t* ins_node; /*!< Innobase SQL insert nodeused to perform insertsto the table */byte*ins_upd_rec_buff;/*!< buffer for storing data convertedto the Innobase format from the MySQLformat */mysql_row_templ_t* mysql_template;/*!< template used to transformrows fast between MySQL and Innobaseformats; memory for this templateis not allocated from 'heap' */btr_pcur_t* pcur;/*!< persistent cursor used in selectsand updates */};


    推荐阅读