MySQL8.0: Serialized Dictionary Information(SDI) 浅析
轉(zhuǎn)自:?https://yq.aliyun.com/articles/600183
SDI是Serialized Dictionary Information的縮寫,是MySQL8.0重新設(shè)計數(shù)據(jù)詞典后引入的新產(chǎn)物。我們知道MySQL8.0開始已經(jīng)統(tǒng)一使用InnoDB存儲引擎來存儲表的元數(shù)據(jù)信息,但對于非InnoDB引擎,MySQL提供了另外一中可讀的文件格式來描述表的元數(shù)據(jù)信息,在磁盤上以 $tbname.sdi的命名存儲在數(shù)據(jù)庫目錄下。
你可以基于sdi文件來對非事務(wù)引擎表進行導出,導入操作,具體參閱官方文檔
而對于InnoDB表沒有創(chuàng)建sdi文件,而是將sdi信息冗余存儲到表空間中(臨時表空間和undo表空間除外)。
既然已經(jīng)有了新的數(shù)據(jù)詞典系統(tǒng),為什么還需要冗余的sdi信息呢,這主要從幾個方面考慮:
- 當數(shù)據(jù)詞典損壞時,實例可能拒絕啟動,在這種情況下我們可以通過冗余的sdi信息,將數(shù)據(jù)拷貝到另外一個實例上,并進行數(shù)據(jù)重建
- 可以離線的查看表的定義
- 可以基于此實現(xiàn)簡單的數(shù)據(jù)轉(zhuǎn)儲
- MySQL Cluster/Ndb也可能依賴SDI信息進行元數(shù)據(jù)同步
官方提供了一個工具叫做ibd2sdi,在安裝目錄下可以找到,可以離線的將ibd文件中的冗余存儲的sdi信息提取出來,并以json的格式輸出到終端。
ibd2sdi工具的使用文檔
相關(guān)worklog:?WL#7069
下面簡單的試玩下:
root@test 02:59:12>create table t1 (a int primary key, b char(10)); Query OK, 0 rows affected (0.02 sec)通過ibd2sdi查看ibd文件
$bin/ibd2sdi data/test/t1.ibd // 默認情況下打印所有信息 // 包含所有的列,索引的各個屬性也可以查詢部分信息:$bin/ibd2sdi --skip-data data/test/t1.ibd ["ibd2sdi" , {"type": 1,"id": 701 } , {"type": 2,"id": 235 } ]$bin/ibd2sdi --id 235 data/test/t1.ibd ["ibd2sdi" , {"type": 2,"id": 235,"object":{"mysqld_version_id": 80011,"dd_version": 80011,"sdi_version": 1,"dd_object_type": "Tablespace","dd_object": {"name": "test/t1","comment": "","options": "","se_private_data": "flags=16417;id=212;server_version=80011;space_version=1;","engine": "InnoDB","files": [{"ordinal_position": 1,"filename": "./test/t1.ibd","se_private_data": "id=212;"}]} } } ]當然還有很多其他的選項(ib2sdi --help),感興趣的可以自行把玩。
首先ibd文件的第一個page中標記了是否存在sdi信息:FSP_FLAGS_POS_SDI,如果是從老版本(例如5.7)
物理恢復過來的數(shù)據(jù),該標記位是未設(shè)置的。
在建表時,sdi相關(guān)堆棧如下:
ha_innobase::create |--> innobase_basic_ddl::create_impl|--> create_table_info_t::create_table|--> create_table_info_t::create_table_def|--> row_create_table_for_mysql|--> dict_build_table_def|--> dict_build_tablespace_for_table|--> btr_sdi_create_indexbtr_sdi_create_index:
- 從代碼來看,sdi index也是按照一個普通btree的標準函數(shù)(btr_create)來創(chuàng)建的,但其對應(yīng)的page類型為FIL_PAGE_SDI
-
內(nèi)存中有一個和tablespace_id對應(yīng)的dict_table_t對象,稱作sdi table(dict_sdi_get_table), 表上包含4個列:
- type
- id
- compressed_len
- uncompressed_len
- data(blob
- sdi table的table_id從tablespace id中生成(dict_sdi_get_table_id)
- sdi table上包含一個索引,索引列為(type, id), ref:?dict_sdi_create_idx_in_mem
- sdi pindex的root page no及sdi版本號被寫到表空間的第一個page中(fsp_sdi_write_root_to_page)
- 另外在之前版本中ibd文件的初始化大小為4個page,而到了8.0版本變成了7個page(FIL_IBD_FILE_INITIAL_SIZE),包括:
在創(chuàng)建完table對象后,需要更新全局數(shù)據(jù)詞典(create_table_info_t::create_table_update_global_dd)
寫入tablespace信息到sdi中
innobase_basic_ddl::create_impl |--> create_table_info_t::create_table_update_global_dd|--> dd_create_implicit_tablespace|--> create_dd_tablespace|--> dd::cache::Dictionary_client::store|--> dd::cache::Storage_adapter::store|--> dd::sdi::store|--> dd::sdi_tablespace::store_tsp_sdi|--> dict_sdi_setid=220
寫入table信息到sdi中,包含了完整表的定義,每個列的屬性信息等
ha_create_table |-->dd::cache::Dictionary_client::update<dd::Table> |-->dd::cache::Storage_adapter::store<dd::Table>|-->dd::sdi::store|-->dd::(anonymous namespace)::with_schema<long long unsigned int, dd::sdi::store|--> operator() |--> dd::sdi_tablespace::store_tbl_sdi|--> apply_to_tablespaces //sdi_tablespace.cc:140|--> ...|--> dict_sdi_set- Server層提供的sdi接口:
- 構(gòu)建sdi序列化詞典信息的入口函數(shù):?dd::serialize, 這里會產(chǎn)生一個字符串,存儲sdi信息
- 調(diào)用innodb接口函數(shù)dict_sdi_set,將數(shù)據(jù)插入到其sdi index中,接口使用innodb api/api0api.cc(之前只由memcached使用)
- 實際存儲的數(shù)據(jù)是經(jīng)過壓縮的,壓縮算法為zlib(Sdi_Compressor)
- 向ibd中寫入記錄(ib_sdi_set),如果存在duplicate key,則更新記錄
- 之前介紹過sdi index中存在lob字段,其外部存儲頁的類型為FIL_PAGE_SDI_BLOB或者FIL_PAGE_SDI_ZBLOB
- 當使用general tablespace時,sdi index中會存儲多條數(shù)據(jù)
總結(jié)
以上是生活随笔為你收集整理的MySQL8.0: Serialized Dictionary Information(SDI) 浅析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 取悦自己什么意思 怎么理解取悦自己的意思
- 下一篇: javap命令参数