MySQL · myrocks · data dictionary 分析

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云原生数据库 PolarDB 分布式版,标准版 2核8GB
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: data dictionaryrocksdb作为mysql的一个新的存储引擎,在存储引擎层,会维护自已的元数据信息。在innodb存储引擎中,我们通过information_schema下的INNODB_SYS_DATAFILES,INNODB_SYS_TABLES,INNODB_SYS_INDEXES等表, 可以窥视innodb的元数据信息。同样,rocksdb通过information_

data dictionary

rocksdb作为mysql的一个新的存储引擎,在存储引擎层,会维护自已的元数据信息。在innodb存储引擎中,我们通过information_schema下的INNODB_SYS_DATAFILES,INNODB_SYS_TABLES,INNODB_SYS_INDEXES等表,
可以窥视innodb的元数据信息。同样,rocksdb通过information_schema下的ROCKSDB_INDEX_FILE_MAP,ROCKSDB_DDL,ROCKSDB_GLOBAL_INFO等表可以查看原数据信息。

show create table ROCKSDB_INDEX_FILE_MAP\G
*************************** 1. row ***************************
       Table: ROCKSDB_INDEX_FILE_MAP
Create Table: CREATE TEMPORARY TABLE `ROCKSDB_INDEX_FILE_MAP` (
  `COLUMN_FAMILY` int(4) NOT NULL DEFAULT '0',
  `INDEX_NUMBER` int(4) NOT NULL DEFAULT '0',
  `SST_NAME` varchar(193) NOT NULL DEFAULT '',
  `NUM_ROWS` bigint(8) NOT NULL DEFAULT '0',
  `DATA_SIZE` bigint(8) NOT NULL DEFAULT '0',
  `ENTRY_DELETES` bigint(8) NOT NULL DEFAULT '0',
  `ENTRY_SINGLEDELETES` bigint(8) NOT NULL DEFAULT '0',
  `ENTRY_MERGES` bigint(8) NOT NULL DEFAULT '0',
  `ENTRY_OTHERS` bigint(8) NOT NULL DEFAULT '0'
) ENGINE=MEMORY DEFAULT CHARSET=utf8

show create table ROCKSDB_DDL\G
*************************** 1. row ***************************
       Table: ROCKSDB_DDL
Create Table: CREATE TEMPORARY TABLE `ROCKSDB_DDL` (
  `TABLE_SCHEMA` varchar(193) NOT NULL DEFAULT '',
  `TABLE_NAME` varchar(193) NOT NULL DEFAULT '',
  `PARTITION_NAME` varchar(193) DEFAULT NULL,
  `INDEX_NAME` varchar(193) NOT NULL DEFAULT '',
  `COLUMN_FAMILY` int(4) NOT NULL DEFAULT '0',
  `INDEX_NUMBER` int(4) NOT NULL DEFAULT '0',
  `INDEX_TYPE` smallint(2) NOT NULL DEFAULT '0',
  `KV_FORMAT_VERSION` smallint(2) NOT NULL DEFAULT '0',
  `CF` varchar(193) NOT NULL DEFAULT ''
) ENGINE=MEMORY DEFAULT CHARSET=utf8

show create table ROCKSDB_GLOBAL_INFO\G
*************************** 1. row ***************************
       Table: ROCKSDB_GLOBAL_INFO
Create Table: CREATE TEMPORARY TABLE `ROCKSDB_GLOBAL_INFO` (
  `TYPE` varchar(513) NOT NULL DEFAULT '',
  `NAME` varchar(513) NOT NULL DEFAULT '',
  `VALUE` varchar(513) NOT NULL DEFAULT ''
) ENGINE=MEMORY DEFAULT CHARSET=utf8

元数据详情

下面我们来具体看看rocksdb维护了哪些元数据信息,从源码中看定义了以下类型,这些数据都以KV的形式存储在名叫__system__的系统column family中。

  // Data dictionary types
  enum DATA_DICT_TYPE {
    DDL_ENTRY_INDEX_START_NUMBER= 1,
    INDEX_INFO=                   2,
    CF_DEFINITION=                3,
    BINLOG_INFO_INDEX_NUMBER=     4,      
    DDL_DROP_INDEX_ONGOING=       5,
    INDEX_STATISTICS=             6,      
    MAX_INDEX_ID=                 7,
    DDL_CREATE_INDEX_ONGOING=     8,
    END_DICT_INDEX_ID=          255
  };
  
  • DDL_ENTRY_INDEX_START_NUMBER
    表和索引之间的映射关系
    key: Rdb_key_def::DDL_ENTRY_INDEX_START_NUMBER(0x1) + dbname.tablename
    value: version + {global_index_id}*n_indexes_of_the_table

  • INDEX_INFO
    索引id和索引属性的关系
    key: Rdb_key_def::INDEX_INFO(0x2) + global_index_id
    value: version, index_type, key_value_format_version
    index_type:主键/二级索引/隐式主键
    key_value_format_version: 记录存储格式的版本

  • CF_DEFINITION
    column family属性
    key: Rdb_key_def::CF_DEFINITION(0x3) + cf_id
    value: version, {is_reverse_cf, is_auto_cf}
    is_reverse_cf: 是否是reverse column family
    is_auto_cf: column family名字是否是$per_index_cf,名字自动由table.indexname组成

  • BINLOG_INFO_INDEX_NUMBER
    binlog位点及gtid信息,binlog_commit更新此信息
    key: Rdb_key_def::BINLOG_INFO_INDEX_NUMBER (0x4)
    value: version, {binlog_name,binlog_pos,binlog_gtid}

  • DDL_DROP_INDEX_ONGOING
    等待删除的索引信息
    key: Rdb_key_def::DDL_DROP_INDEX_ONGOING(0x5) + global_index_id
    value: version

  • INDEX_STATISTICS
    索引统计信息
    key: Rdb_key_def::INDEX_STATISTICS(0x6) + global_index_id
    value: version, {materialized PropertiesCollector::IndexStats}

  • MAX_INDEX_ID
    当前的index id,每次创建索引index id都从这个获取和更新
    key: Rdb_key_def::CURRENT_MAX_INDEX_ID(0x7)
    value: version, current max index id

  • DDL_CREATE_INDEX_ONGOING
    等待创建的索引信息
    key: Rdb_key_def::DDL_CREATE_INDEX_ONGOING(0x8) + global_index_id
    value: version

rocksdb DDL 实现

这里以建表和删表来举例

  • create table
CREATE TABLE t1 (a INT, b CHAR(8), pk INT AUTO_INCREMENT ,PRIMARY KEY(pk), key idx1(b) comment 'cf_1') ENGINE=rocksdb;

通过以下步骤建表

  1. 创建column family (get_or_create_cf)
    primary key 存在default column family中,idx1存在cf_1中,需增加一条cf_1的,CF_DEFINITION的记录
    {CF_DEFINITION(4)+cf_id(4)} —> {CF_DEFINITION_VERSION(2)+cf_flags(4)}

  2. 创建索引
    两条索引
    {INDEX_INFO(4)+cf_id(0)+index_id(260)—> { INDEX_INFO_VERSION_VERIFY_KV_FORMAT(1)+index_type(1)+kv_version(11)
    {INDEX_INFO(4)+cf_id(2)+index_id(261)—> { INDEX_INFO_VERSION_VERIFY_KV_FORMAT(2)+index_type(2)+kv_version(11)

  3. 建立表和索引的映射
    {DDL_ENTRY_INDEX_START_NUMBER(4)+dbname(test)+tablename(t1) } –> { DDL_ENTRY_INDEX_VERSION+cf_id(0)+index_id(260)+cf_id(2)+index_id(261}

以上信息通过同一batch一起存入rocksdb中。

另外,建索引时,会更新MAX_INDEX_ID信息,使用单独的batch写入,参考(Rdb_seq_generator::get_and_update_next_number)

select * from INFORMATION_SCHEMA.ROCKSDB_DDL where table_name='t1';
+--------------+------------+----------------+------------+---------------+--------------+------------+-------------------+---------+
| TABLE_SCHEMA | TABLE_NAME | PARTITION_NAME | INDEX_NAME | COLUMN_FAMILY | INDEX_NUMBER | INDEX_TYPE | KV_FORMAT_VERSION | CF      |
+--------------+------------+----------------+------------+---------------+--------------+------------+-------------------+---------+
| test         | t1         | NULL           | PRIMARY    |             0 |          260 |          1 |                11 | default |
| test         | t1         | NULL           | idx1       |             2 |          261 |          2 |                11 | cf_1    |
+--------------+------------+----------------+------------+---------------+--------------+------------+-------------------+---------+

select d.*,i.* from INFORMATION_SCHEMA.ROCKSDB_INDEX_FILE_MAP i,INFORMATION_SCHEMA.ROCKSDB_DDL d where i.INDEX_NUMBER=d.INDEX_NUMBER;
+--------------+------------+----------------+------------+---------------+--------------+------------+-------------------+---------+---------------+--------------+------------+----------+-----------+---------------+---------------------+--------------+--------------+
| TABLE_SCHEMA | TABLE_NAME | PARTITION_NAME | INDEX_NAME | COLUMN_FAMILY | INDEX_NUMBER | INDEX_TYPE | KV_FORMAT_VERSION | CF      | COLUMN_FAMILY | INDEX_NUMBER | SST_NAME   | NUM_ROWS | DATA_SIZE | ENTRY_DELETES | ENTRY_SINGLEDELETES | ENTRY_MERGES | ENTRY_OTHERS |
+--------------+------------+----------------+------------+---------------+--------------+------------+-------------------+---------+---------------+--------------+------------+----------+-----------+---------------+---------------------+--------------+--------------+
| test         | t1         | NULL           | PRIMARY    |             0 |          260 |          1 |                11 | default |             0 |          260 | 000025.sst |        2 |        42 |             0 |                   0 |            0 |            0 |
| test         | t1         | NULL           | idx1       |             2 |          261 |          2 |                11 | cf_1    |             2 |          261 | 000027.sst |        2 |        42 |             0 |                   0 |            0 |            0 |
+--------------+------------+----------------+------------+---------------+--------------+------------+-------------------+---------+---------------+--------------+------------+----------+-----------+---------------+---------------------+--------------+--------------+
2 rows in set (0.00 sec)

实际数据分布如下图:
levedb_columfamily__

元数据分布在系统column family __system__中
primary key 分布在column family default中
idx1 分布在column family cf_1中
黄线之间代表数据分布的范围

  • drop table
drop table t1;

batch->Put 将索引加入到待删的kv队列中
{DDL_DROP_INDEX_ONGOING(4)+cf_id(0)+index_id(260)} –> {DDL_DROP_INDEX_ONGOING_VERSION(2)}
{DDL_DROP_INDEX_ONGOING(4)+cf_id(2)+index_id(261)} –> {DDL_DROP_INDEX_ONGOING_VERSION(2)}
batch->Delete 删除表的映射关系
表和索引的映射关系

后台线程再从待删的kv队列取出待删的索引,通过 DeleteFilesInRange, CompactRange 删除索引数据。
后台线程确定索引数据删除完成后,batch删除相应的DDL_DROP_INDEX_ONGOING和INDEX_INFO的索引信息。

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
8天前
|
关系型数据库 MySQL 索引
mysql 分析5语句的优化--索引添加删除
mysql 分析5语句的优化--索引添加删除
11 0
|
3月前
|
关系型数据库 MySQL Serverless
高顿教育:大数据抽数分析业务引入polardb mysql serverless
高顿教育通过使用polardb serverless形态进行数据汇总,然后统一进行数据同步到数仓,业务有明显高低峰期,灵活的弹性伸缩能力,大大降低了客户使用成本。
|
3月前
|
关系型数据库 MySQL 索引
【MySQL 解析】Hash索引和B+树索引对比分析
【1月更文挑战第11天】【MySQL 解析】Hash索引和B+树索引对比分析
|
3月前
|
SQL 关系型数据库 MySQL
mysql事务原理分析
mysql事务原理分析
26 0
|
3月前
|
缓存 固态存储 关系型数据库
MySQL性能优化指南:深入分析重做日志刷新到磁盘的机制
MySQL性能优化指南:深入分析重做日志刷新到磁盘的机制
|
19天前
|
SQL 关系型数据库 MySQL
【MySQL技术专题】「问题实战系列」深入探索和分析MySQL数据库的数据备份和恢复实战开发指南(8.0版本升级篇)
【MySQL技术专题】「问题实战系列」深入探索和分析MySQL数据库的数据备份和恢复实战开发指南(8.0版本升级篇)
93 0
|
8天前
|
SQL 缓存 关系型数据库
mysql性能优化-慢查询分析、优化索引和配置
mysql性能优化-慢查询分析、优化索引和配置
75 0
|
14天前
|
缓存 关系型数据库 MySQL
MySQL 查询优化:提速查询效率的13大秘籍(索引设计、查询优化、缓存策略、子查询优化以及定期表分析和优化)(中)
MySQL 查询优化:提速查询效率的13大秘籍(索引设计、查询优化、缓存策略、子查询优化以及定期表分析和优化)(中)
|
2月前
|
SQL 关系型数据库 MySQL
MySQL技能完整学习列表10、数据导入和导出——1、数据导入(LOAD DATA, mysqldump)——2、数据导出(SELECT ... INTO OUTFILE, mysqldump)
MySQL技能完整学习列表10、数据导入和导出——1、数据导入(LOAD DATA, mysqldump)——2、数据导出(SELECT ... INTO OUTFILE, mysqldump)
48 0
|
16天前
|
SQL 关系型数据库 MySQL
【MySQL】慢SQL分析流程
【4月更文挑战第1天】【MySQL】慢SQL分析流程

相关产品

  • 云数据库 RDS MySQL 版
  • 推荐镜像

    更多