InnoDB數據字典--字典表加載
在InnoDB啟動時,如果是新建數據庫則需初始化庫,需要創建字典管理的相關信息。函數innobase_start_or_create_for_mysql調用dict_create完成此功能。即創建數據字典,因為InnoDB系統表的個數結構固定,所以初始化庫的時候只需要創建這幾個表的B+樹即可並將B+樹的根頁號存放到固定位置。對於B+樹,只要找到根頁面,就可以從根頁面開始檢索數據。相關系統表(即上一節講到的4個系統表)在InnoDB內部,不會暴露給用戶。
4個系統表通過固定的硬編碼進行構建。具體原理流程如下。
2、數據字典創建及加載原理流程
3、說明
1)innobase_start_or_create_for_mysql函數調用dict_create()函數進行數據字典的創建和加載工作。
2)dict_hdr_create完成系統表空間第7號頁面dict header的初始化及創建SYS_TABLES兩個索引、SYS_COLUMNS一個索引、SYS_INDEXES一個索引、SYS_FIELDS一個索引,其創建索引的函數是btr_create。
3)創建B+樹索引後,通過dict_boot函數加載常駐內存的4個系統表。具體流程見流程圖的②部分。
4)加載完成後,將這4個系統表掛在一個全局字典中:
dict0dict.h::
/* Dictionary system struct */ struct dict_sys_t{ ib_mutex_t mutex; /*!< mutex protecting the data dictionary; protects also the disk-based dictionary system tables; this mutex serializes CREATE TABLE and DROP TABLE, as well as reading the dictionary data for a table from system tables */ row_id_t row_id; /*!< the next row id to assign; NOTE that at a checkpoint this must be written to the dict system header and flushed to a file; in recovery this must be derived from the log records */ hash_table_t* table_hash; /*!< hash table of the tables, based on name */ hash_table_t* table_id_hash; /*!< hash table of the tables, based on id */ ulint size; /*!< varying space in bytes occupied by the data dictionary table and index objects */ dict_table_t* sys_tables; /*!< SYS_TABLES table */ dict_table_t* sys_columns; /*!< SYS_COLUMNS table */ dict_table_t* sys_indexes; /*!< SYS_INDEXES table */ dict_table_t* sys_fields; /*!< SYS_FIELDS table */ /*=============================*/ UT_LIST_BASE_NODE_T(dict_table_t) table_LRU; /*!< List of tables that can be evicted from the cache */ UT_LIST_BASE_NODE_T(dict_table_t) table_non_LRU; /*!< List of tables that can‘t be evicted from the cache */ };
結構體中sys_tables、sys_columns、sys_indexes、sys_fields四個結構存儲上述對應的4個系統表。
結構體中HASH表及鏈表用來存儲InnoDB中的所有表的緩存,包括系統表及用戶表。table_hash哈希表按名字緩存,table_id_hash按表ID進行hash,LRU鏈表用來管理表對象緩存。
5)普通用戶表加載流程見流程圖的③、④部分。
當用戶訪問一個用戶表時,首先需要從表對象緩存中查找這個表的SHARE對象,如果找到則直接從其實例化表對象鏈表中拿一個使用;如果沒有找到,則需要重新打開這個表,需要找到這個表的字典信息。即③的流程。
具體加載一個表的字典是④流程,dict_load_table的工作。
a)首先需要找到SYS_TABLES表,也是先找緩存,緩存找不到再從系統表加載: dict_table_get_low
b)找到之後構建一個查詢鍵值,從SYS_TABLES的name主鍵索引進行查詢,如果誒呦找到或者該記錄已經被刪除則返回,否則解析找到的這條記錄。然後根據這些信息創建表的內存對象table。
c)加載列操作與加載表的原理基本一樣,對應系統表的SYS_COLUMNS,聚集索引為(TABLE_ID,POS),查找時,如果TABLE_ID相同,在POS從小到大排序,所以構造所有列的鍵值時,只需要通過TABLE_ID查詢即可,按順序取出所有列信息一一構造內存對象。
d)加載索引信息類似的流程
InnoDB數據字典--字典表加載