转自: https://yq.aliyun.com/articles/600183

SDI是Serialized Dictionary Information的缩写,是MySQL8.0重新设计数据词典后引入的新产物。我们知道MySQL8.0开始已经统一使用InnoDB存储引擎来存储表的元数据信息,但对于非InnoDB引擎,MySQL提供了另外一中可读的文件格式来描述表的元数据信息,在磁盘上以 $tbname.sdi的命名存储在数据库目录下。

你可以基于sdi文件来对非事务引擎表进行导出,导入操作,具体参阅官方文档

而对于InnoDB表没有创建sdi文件,而是将sdi信息冗余存储到表空间中(临时表空间和undo表空间除外)。

既然已经有了新的数据词典系统,为什么还需要冗余的sdi信息呢,这主要从几个方面考虑:

  • 当数据词典损坏时,实例可能拒绝启动,在这种情况下我们可以通过冗余的sdi信息,将数据拷贝到另外一个实例上,并进行数据重建
  • 可以离线的查看表的定义
  • 可以基于此实现简单的数据转储
  • MySQL Cluster/Ndb也可能依赖SDI信息进行元数据同步

官方提供了一个工具叫做ibd2sdi,在安装目录下可以找到,可以离线的将ibd文件中的冗余存储的sdi信息提取出来,并以json的格式输出到终端。

ibd2sdi工具的使用文档

相关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)
物理恢复过来的数据,该标记位是未设置的。

在建表时,sdi相关堆栈如下:

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_index

btr_sdi_create_index:

  • 从代码来看,sdi index也是按照一个普通btree的标准函数(btr_create)来创建的,但其对应的page类型为FIL_PAGE_SDI
  • 内存中有一个和tablespace_id对应的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),包括:
0: file space header
1: insert buffer bitmap
2: inode page
3: sdi index page
4: index page
5: freshly allocated page
6: freshly allocated page

在创建完table对象后,需要更新全局数据词典(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_set

id=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接口:
[$/MySQL_8.0/sql/dd/impl]
$ls * | grep sdi
sdi_api.cc
sdi.cc
sdi_file.cc
sdi.h
sdi_impl.h
sdi_tablespace.cc
sdi_tablespace.h
sdi_utils.h
  • 构建sdi序列化词典信息的入口函数: dd::serialize, 这里会产生一个字符串,存储sdi信息
  • 调用innodb接口函数dict_sdi_set,将数据插入到其sdi index中,接口使用innodb api/api0api.cc(之前只由memcached使用)
  • 实际存储的数据是经过压缩的,压缩算法为zlib(Sdi_Compressor)
  • 向ibd中写入记录(ib_sdi_set),如果存在duplicate key,则更新记录
  • 之前介绍过sdi index中存在lob字段,其外部存储页的类型为FIL_PAGE_SDI_BLOB或者FIL_PAGE_SDI_ZBLOB
  • 当使用general tablespace时,sdi index中会存储多条数据

MySQL8.0: Serialized Dictionary Information(SDI) 浅析相关推荐

  1. MySQL-8.0 | 数据字典最强解读

    公众号展示代码会自动折行,建议横屏阅读 1. 引言 数据字典(Data Dictionary)中存储了诸多数据库的元数据信息如图1所示,包括基本Database, table, index, colu ...

  2. mysql存储字典,详解MySQL-8.0数据字典

    1. 引言 数据字典(Data Dictionary)中存储了诸多数据库的元数据信息如图1所示,包括基本Database, table, index, column, function, trigge ...

  3. MySQL8.0 ibd2sdi 根据ibd文件恢复表结构

    ibd文件 在8之前InnoDB存储表的结构和数据时,分别存储在frm文件和ibd文件.而在8的时候全都存到了ibd文件里...... 如果你把mysql搞崩了-比如我手贱把preformance_s ...

  4. MySQL8.0地理空间数据库的QGIS应用浅析

    目录 一.认识空间数据 二.认识空间数据库 三.MySQL8.0空间数据库 点数据建表 线数据建表 面数据建表 添加数据 四.QGIS中使用MySQL作为数据源 五.总结 本文的概念性内容均为作者的个 ...

  5. mysql为什么直接8.0_为什么要迁移到MySQL8.0?

    原标题:为什么要迁移到MySQL8.0? 来自公众号:老叶茶馆,作者:lefred,翻译:徐晨亮 原文链接:https://lefred.be/content/replace-mariadb-10-3 ...

  6. MySQL8.0版本升级建议及各类场景的操作方法

    点击上方"蓝字" 关注我们,享更多干货! 01 升级版本选择原则和建议 MySQL的升级需要遵循以下几条原则和建议: 支持从MySQL5.7升级到8.0,注意仅支持GA版本之间的升 ...

  7. mysql8.0 的新特性_What's New In MySQL 8.0(MySQL 8.0 新特性)

    由于8.0内有很多C++11特性.需要gcc4.8版本以上.Rhel6系列默认gcc是4.7.在安装gcc6.1之后仍然检查不过. 原因可能是6.1版本不一定高于4.7,暂不讨论.鉴于升级gcc耗时较 ...

  8. MySQL8.0 存储引擎(InnoDB )buffer pool的实现原理

    数据库为了高效读取和存储物理数据,通常都会采用缓存的方式来弥补磁盘IO与CPU运算速度差.InnoDB 作为一个具有高可靠性和高性能的通用存储引擎也不例外,Buffer Pool就是其用来在内存中缓存 ...

  9. MySQL8.0 - 新特性 - Instant Add Column

    MySQL8.0开始对一些DDL操作做了大量的优化,例如原子DDL, 快速DDL(只修改元数据),前者解决了长期以来mysql的一大诟病,后者则提升了dba同学的生活品质 官方文档列出了一些可以快速d ...

最新文章

  1. SQLHelper类
  2. for和foreach分析
  3. 计组-I/O系统的基本概念
  4. 酷派android是什么系统版本,酷派大神X7的手机系统是什么?能升级安卓5.0吗?
  5. Linux运维:现状、入门和未来之路
  6. java 判断日期为第几天
  7. 要闻君说:谷歌云重磅发布两大技术平台;以后可以打飞滴了?SAP重组动荡;微软宣布 Azure Functions 支持 Java...
  8. python解释器环境中用于表示上一次运算结果的特殊变量_判断正误 PUSH CL_学小易找答案...
  9. restorecon命令
  10. 阿里北大:深度哈希算法最新综述
  11. 喜欢初音未来的桌面壁纸看过来
  12. Android简单的TXT文件存储
  13. 移动应用开发者在区块链中怎么赚钱?
  14. Hillstone设备管理-许可证安装
  15. 转载:数据库应用开发工具Toad使用笔记
  16. 修复计算机之后东西还在吗,硬盘分区表修复后文件还在吗
  17. 服务器装系统步骤图解win7,win7 硬盘重装系统步骤图解|win7系统硬盘重装教程
  18. Vue install 报错 code EINTEGRITY
  19. 双系统双硬盘的linux引导,双硬盘双系统Grub引导的配置
  20. mysql索引linke和等于_MySQL索引介绍和实战

热门文章

  1. P4137 Rmq Problem / mex 主席树求mex
  2. P3403 跳楼机 同余最短路
  3. gym 102875 H. Happy Morse Code
  4. Desert King POJ - 2728
  5. CF1444C Team-Building(可持久化并查集)(二分图)
  6. NOIP2012:疫情控制(二分、贪心、树上倍增)
  7. jzoj3302-[集训队互测2013]供电网络【上下界网络流,费用流,动态加边】
  8. 【2018.5.19】模拟赛之二-ssl2433 文件名排序【字符串】
  9. Korney Korneevich and XOR(CF750F1/F2)
  10. 北方大学 ACM 多校训练赛 第十五场 欢度6.18