myrocks之数据字典

justforfun justforfun     2022-08-11     586

关键词:

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_MAPG
************************* 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_DDLG
*********************** 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_INFOG
*********************** 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;

    通过以下步骤建表

    • 创建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)}
    • 创建索引 两条索引 {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)
    • 建立表和索引的映射 {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)

 

实际数据分布如下图:
技术分享

元数据分布在系统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的索引信息。




































myrocks记录格式分析

 概况rocksdb作为KV存储引擎,那么myrocks记录最终会以kv的形式存储在rocksdb中。MySQL中的表一般由若干索引组成,在innodb存储引擎中,每个索引对应一颗B树,而在rocksdb存储引擎中,索引对应于rocksdb中一段连续范围的数据。具体... 查看详情

python数据类型之字典(代码片段)

...任意的字典是通过键:值对的方式存储的,可以存储大量数据,查找方便迅速。有明确的对应关系时,推荐使用字典json字典比较消耗内存2.字典的增删改查增加:dic["键"]="值&qu 查看详情

权限管理系统之字典(代码)管理

...码(字典)管理系统代码是平台内置的、通用的、统一的数据描述。代码管理(数据字典)是整个平台中数据描述的有效机制。通过界面进行可视化的操作和维护,能快速录入和修改平台上统一的字典数据。有效提高了数据的重... 查看详情

数据结构与算法之字典(代码片段)

字典基于Array类构造一个字典类用于储存键值对(之前一直不知道JS的Array原来可以存储键值对,第一次看到简直惊呆了)暂时看到的内容挺简单的,不明白这个的存在意义是什么,感觉还不如直接用JSON来得直接。直接上代码不... 查看详情

前端学数据结构之字典和散列表

...当作主要元素。在字典中,我们用[键,值]的形式来存储数据。在散列表中也是一样(也是以[键,值]对的形式来存储数据)。但是两种数据结构的实现方式略有不同,本文将详细介绍字典和散列表这两种数据结构 字典  ... 查看详情

myrocks文档-init

原文地址:https://github.com/facebook/mysql-5.6/wiki因为最近要用到MyRocks,所以文档还是要看看的,翻译不对的地方大家多多指正,谢谢。【目录】Overview 2017-2-321:00:00【Init...】  查看详情

数据类型之列表元组字典

数据类型|表示形式| 是否有序列|对象是否可变|访问顺序数字  | 1234 |  没有下标 | 不可变|直接访问字符串|‘asd3234‘|  有下标  |  不可变 |序列访问元组 tuple|(1,‘ab... 查看详情

objective-c中数据类型之四字典(nsdictionary)

//1.字典初始化、赋值方式1NSMutableDictionary*m_dictionary=[[NSMutableDictionaryalloc]initWithCapacity:0];[m_dictionarysetObject:@1forKey:@"语文"];[m_dictionarysetObject:@2forKey:@"数学"];[m_dictionarysetObject:@3fo 查看详情

数据分析之道-基础知识字典(代码片段)

...创作者,专注于分享python领域知识。✍本文录入于《数据分析之道》,本专栏针对大学生、初级数据分析工程师精心打造,对python基础知识点逐一击破,不断学习,提升自我。✍订阅后,可以阅读《数据分... 查看详情

redis数据结构之字典/哈希表(代码片段)

Redis是以字典(关联数组)的形式存储的,一个key对应一个value。在字符串类型中,value只能是一个字符串。那么在散列类型,也叫哈希类型中,value对应的也是一个字典(关联数组)。那么就可以理解,Redis的哈希类型/散列类型... 查看详情

redis数据结构之dict字典(代码片段)

...#xff0c;是一种用于保存键值对(key-valuepair)的抽象数据结构,其应用于将一个键(key)映射为一个值,从而形成关联性。在字典中,每个键都是独一无二的,通过独一无二的特性来获取、更新、删除... 查看详情

系统基础模块之通用字典项目管理

...途类别、用车评价、车辆状态等等信息,这些是很简单的数据,用来给业务功能使用的,是一个下拉列表形的数据,如果我们为每个这样的简单类型都创建一个表的话,那么有以下坏处:1) 如 查看详情

myrocks文档-gettingstartedwithmyrocks

GettingStartedwithMyRocksDownloadFacebookMySQL5.6,thenbuildfromsource安装步骤,这都不会就不用往下做了,直接给连接https://github.com/facebook/mysql-5.6/wiki/Build-StepsSetupmy.cnf想要把RocksDB引擎给启动起来,你至需要把至少下面这一些参数给写到my.cnf文... 查看详情

数据类型之字典介绍(代码片段)

1、作用字典可以用来存储含有描述性信息的数据,可读性比其他类型高,比如"name":"wu","age":24它是以键值对的形式存储数据2、定义:内用逗号分隔开多个key:value,其中value可以使任意类型,但是key必须是不可变类型,且不能重复造... 查看详情

测开之数据类型进阶篇・第二篇《字典和集合的原理应用》(代码片段)

目录集合什么是集合?定义空集合集合的特点-自动去重集合常用的方法空集合添加元素add()删除集合元素remove()更新元素update()清空集合元素clear()复制元素copy()字典和集合的存储原理关于集合、字典、元祖、列表性能分析集... 查看详情

redis源码剖析-redis内置数据结构之字典dict

...来讲讲Redis中的哈希表。哈希表在C++中对应的是map数据结构,但在Redis中称作dict(字典)。Redis只是用 查看详情

pyhton编程之基本数据类型-列表元组字典

一:列表(list)  列表是由一系列按特定顺序排列的元素组成,可以创建包含字母表中的所有字母、数字、或中文的列表,也可以将任何东西加入列表中,其中的元素之间可以没有任何关系。  在Python中,用方括号[]来表示... 查看详情

第八篇基本数据类型之列表元组与字典(代码片段)

列表写在最前,必须要会的:append(),extend(),insert(),索引,切片,循环 list 是一个类,是个对象列表用 方括号[]括起来的,[]内以逗号分割每个元素,列表中的元素可以是数字,字符串,列表,布尔值,字典... 查看详情