我们最近看到MySQL 8.0 中的 MyISAM 表已经在某种程度上替换了.frm文件(参见这篇文章)。
但是,那些文件是什么?它们可以用于除 MyISAM 表之外的其他用途吗?… 让我们尝试回答这些问题并更熟悉.sdi文件。
SDI 代表什么?
SDI首字母缩写词代表序列化字典信息。

您可能已经知道,MySQL 8.0 取代了将表元数据及其结构存储到新事务数据字典(在 InnoDB 中)的旧方法。
此外,该信息也是任何 InnoDB 表空间的一部分,它被附加到表空间,因此元数据和数据捆绑在一起。
对于不支持此功能的存储引擎,会创建一个外部文件,即实际的SDI。例如,MyISAM 表就是这种情况。
他们看起来怎么样 ?
所以我们知道,对于没有能力存储表元数据的存储引擎,会创建一个 SDI 文件。它是什么样子的 ?
事实上,SDI 文件是一个紧凑的 JSON 文件。它的名称由表的名称和表的 id 组成。
如果我们采用上一篇文章中的示例表,在文件系统上,SDI 文件如下所示:
[root@imac my_isam_db]# ls -l *.sdi
-rw-r----- 1 mysql mysql 3600 8 月 2 日 12:49 t1_5017.sdi
5017 是表的隐藏 ID。
实际上,它是字典对象的 OID 的字符串表示形式。OID 确保唯一性,这是必需的,因为多个表可能映射到相同的名称。
现在让我们看看 JSON 是什么样子的:
{
"mysqld_version_id": 80026,
"dd_version": 80023,
"sdi_version": 80019,
"dd_object_type": "Table",
"dd_object": {
"name": "t1",
"mysql_version_id": 80026,
"created": 20210802104936,
"last_altered": 20210802104936,
"hidden": 1,
"options": "avg_row_length=0;key_block_size=0;keys_disabled=0;pack_record=1;stats_auto_recalc=0;stats_sample_pages=0;",
"columns": [
{
"name": "id",
"type": 4,
"is_nullable": false,
"is_zerofill": false,
"is_unsigned": true,
"is_auto_increment": true,
"is_virtual": false,
"hidden": 1,
"ordinal_position": 1,
"char_length": 10,
"numeric_precision": 10,
"numeric_scale": 0,
"numeric_scale_null": false,
"datetime_precision": 0,
"datetime_precision_null": 1,
"has_no_default": false,
"default_value_null": false,
"srs_id_null": true,
"srs_id": 0,
"default_value": "AAAAAA==",
"default_value_utf8_null": true,
"default_value_utf8": "",
"default_option": "",
"update_option": "",
"comment": "",
"generation_expression": "",
"generation_expression_utf8": "",
"options": "interval_count=0;",
"se_private_data": "",
"engine_attribute": "",
"secondary_engine_attribute": "",
"column_key": 2,
"column_type_utf8": "int unsigned",
"elements": [],
"collation_id": 8,
"is_explicit_collation": false
},
{
"name": "name",
"type": 16,
"is_nullable": true,
"is_zerofill": false,
"is_unsigned": false,
"is_auto_increment": false,
"is_virtual": false,
"hidden": 1,
"ordinal_position": 2,
"char_length": 20,
"numeric_precision": 0,
"numeric_scale": 0,
"numeric_scale_null": true,
"datetime_precision": 0,
"datetime_precision_null": 1,
"has_no_default": false,
"default_value_null": true,
"srs_id_null": true,
"srs_id": 0,
"default_value": "",
"default_value_utf8_null": true,
"default_value_utf8": "",
"default_option": "",
"update_option": "",
"comment": "",
"generation_expression": "",
"generation_expression_utf8": "",
"options": "interval_count=0;",
"se_private_data": "",
"engine_attribute": "",
"secondary_engine_attribute": "",
"column_key": 1,
"column_type_utf8": "varchar(20)",
"elements": [],
"collation_id": 8,
"is_explicit_collation": false
},
{
"name": "inserted",
"type": 18,
"is_nullable": false,
"is_zerofill": false,
"is_unsigned": false,
"is_auto_increment": false,
"is_virtual": false,
"hidden": 1,
"ordinal_position": 3,
"char_length": 19,
"numeric_precision": 0,
"numeric_scale": 0,
"numeric_scale_null": true,
"datetime_precision": 0,
"datetime_precision_null": 0,
"has_no_default": false,
"default_value_null": false,
"srs_id_null": true,
"srs_id": 0,
"default_value": "AAAAAA==",
"default_value_utf8_null": false,
"default_value_utf8": "CURRENT_TIMESTAMP",
"default_option": "CURRENT_TIMESTAMP",
"update_option": "",
"comment": "",
"generation_expression": "",
"generation_expression_utf8": "",
"options": "interval_count=0;",
"se_private_data": "",
"engine_attribute": "",
"secondary_engine_attribute": "",
"column_key": 1,
"column_type_utf8": "timestamp",
"elements": [],
"collation_id": 8,
"is_explicit_collation": false
}
],
"schema_ref": "my_isam_db",
"se_private_id": 18446744073709552000,
"engine": "MyISAM",
"last_checked_for_upgrade_version_id": 0,
"comment": "",
"se_private_data": "",
"engine_attribute": "",
"secondary_engine_attribute": "",
"row_format": 2,
"partition_type": 0,
"partition_expression": "",
"partition_expression_utf8": "",
"default_partitioning": 0,
"subpartition_type": 0,
"subpartition_expression": "",
"subpartition_expression_utf8": "",
"default_subpartitioning": 0,
"indexes": [
{
"name": "PRIMARY",
"hidden": false,
"is_generated": false,
"ordinal_position": 1,
"comment": "",
"options": "flags=0;",
"se_private_data": "",
"type": 1,
"algorithm": 2,
"is_algorithm_explicit": false,
"is_visible": true,
"engine": "MyISAM",
"engine_attribute": "",
"secondary_engine_attribute": "",
"elements": [
{
"ordinal_position": 1,
"length": 4,
"order": 2,
"hidden": false,
"column_opx": 0
}
]
}
],
"foreign_keys": [],
"check_constraints": [],
"partitions": [],
"collation_id": 8
}
}
如您所见,此 SDI 文件包含大量信息。仅供参考,这是表的创建语句:
CREATE TABLE `t1` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`inserted` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SDI 文件是否仅与 MyISAM 一起使用?
该 SDI 文件可用于使用特定语句IMPORT TABLE FROM在 MySQL 8.0 服务器周围复制 MySIAM 表。
SDI 文件还用于无法嵌入元数据信息的任何其他存储引擎。目前只有 InnoDB 和 NDB 不需要任何 SDI 文件。
如果您创建一个 CVS 表,它也会有一个 SDI:
CREATE TABLE `t2` (
`id` int unsigned NOT NULL,
`name` varchar(20) NOT NULL DEFAULT '',
`inserted` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=CSV DEFAULT CHARSET=latin1
[root@imac my_isam_db]# ls -l t2*
-rw-r----- 1 mysql mysql 3268 Aug 11 13:27 t2_5037.sdi
-rw-r----- 1 mysql mysql 35 Aug 11 13:27 t2.CSM
-rw-r----- 1 mysql mysql 0 Aug 11 13:27 t2.CSV
当然,我们也可以从 SDI 文件中检查该信息:
[root@imac my_isam_db]# cat t2_5037.sdi | jq ."dd_object"."engine"
"CSV"
SDI 文件提供元数据冗余。即使对于 InnoDB 表,如果数据字典变得不可用,它也很有用,可以直接从 InnoDB 表空间文件中提取对象元数据。
SDI 信息和 InnoDB
对于 InnoDB 表,可以使用名为ibd2sdi的工具从表空间中提取 SDI 信息。
ibd2sdi 可以在file-per-table 表空间文件(.ibd 文件)、通用表空间文件(.ibd 文件)、系统表空间文件(ibdata* 文件)和数据字典表空间(mysql.ibd)上运行。不支持与临时表空间或撤消表空间一起使用。
让我们用 InnoDB 试试。我刚刚创建了另一个表((t3),就像之前的表一样,但使用 InnoDB 作为存储引擎,并且确实在架构目录中我们可以看到这个单个.ibd文件:
[root@imac my_isam_db]# ls
t1_5017.sdi t1.MYD t1.MYI t2_5037.sdi t2.CSM t2.CSV t3.ibd
现在我们可以从中生成一个 SDI 文件:
# ibd2sdi t3.ibd -d t3.sdi
我们可以解析新创建的 SDI 文件,但 MySQL 不需要它,它只是元数据的额外副本。
我可以手动修改现有的 SDI 文件吗?
当然,这是不推荐的。但是,如果在表已经在 MySQL 中之后删除或修改.sdi文件,服务器将不需要它,因为该结构已经是数据字典的一部分。
每次使用需要 SDI 文件的引擎修改表时,具有不同 OID 编号的新文件将替换最终的前一个文件。
文章来源:https://blogs.oracle.com/mysql/mysql-80%3a-all-you-need-to-know-about-sdi




