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 '',
`INDEX_NUMBER` int(4) NOT NULL DEFAULT '',
`SST_NAME` varchar(193) NOT NULL DEFAULT '',
`NUM_ROWS` bigint(8) NOT NULL DEFAULT '',
`DATA_SIZE` bigint(8) NOT NULL DEFAULT '',
`ENTRY_DELETES` bigint(8) NOT NULL DEFAULT '',
`ENTRY_SINGLEDELETES` bigint(8) NOT NULL DEFAULT '',
`ENTRY_MERGES` bigint(8) NOT NULL DEFAULT '',
`ENTRY_OTHERS` bigint(8) NOT NULL DEFAULT ''
) 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 '',
`INDEX_NUMBER` int(4) NOT NULL DEFAULT '',
`INDEX_TYPE` smallint(2) NOT NULL DEFAULT '',
`KV_FORMAT_VERSION` smallint(2) NOT NULL DEFAULT '',
`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= ,
INDEX_INFO= ,
CF_DEFINITION= ,
BINLOG_INFO_INDEX_NUMBER= ,
DDL_DROP_INDEX_ONGOING= ,
INDEX_STATISTICS= ,
MAX_INDEX_ID= ,
DDL_CREATE_INDEX_ONGOING= ,
END_DICT_INDEX_ID=
};
  • 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(), 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 | | | | | default |
| test | t1 | NULL | idx1 | | | | | 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 | | | | | default | | | .sst | | | | | | |
| test | t1 | NULL | idx1 | | | | | cf_1 | | | .sst | | | | | | |
+--------------+------------+----------------+------------+---------------+--------------+------------+-------------------+---------+---------------+--------------+------------+----------+-----------+---------------+---------------------+--------------+--------------+
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 之数据字典的更多相关文章

  1. MyRocks简介

    RocksDB是facebook基于LevelDB实现的,目前为facebook内部大量业务提供服务.经过facebook大量工作,将RocksDB为MySQL的一个存储引擎移植到MySQL,称之为M ...

  2. MyRocks DDL原理

    最近一个日常实例在做DDL过程中,直接把数据库给干趴下了,问题还是比较严重的,于是赶紧排查问题,撸了下crash堆栈和alert日志,发现是在去除唯一约束的场景下,MyRocks存在一个严重的bug, ...

  3. myrocks复制中断问题排查

    背景 mysql可以支持多种不同的存储引擎,innodb由于其高效的读写性能,并且支持事务特性,使得它成为mysql存储引擎的代名词,使用非常广泛.随着SSD逐渐普及,硬件存储成本越来越高,面向写优化 ...

  4. Oracle数据字典

    数据字典-简介 Oracle数据字典的名称由前缀和后缀组成,使用下划线"_"连接,其代表的含义如下: ● DBA_:包含数据库实例的所有对象信息. ● V$_:当前实例的动态视图, ...

  5. postgresql 导出数据字典文档

    项目上需要整理目前数据库的数据字典文档.项目不规范,这种文档只要后期来补.这么多张表,每个字段都写到word文档里真心头大.就算前面写了个查询表结构的sql,但是最后整理到word里还是感觉有点麻烦. ...

  6. 基于表的数据字典构造MySQL建表语句

    表的数据字典格式如下: 如果手动写MySQL建表语句,确认麻烦,还不能保证书写一定正确. 写了个Perl脚本,可快速构造MySQL脚本语句. 脚本如下: #!/usr/bin/perl use str ...

  7. 使用 PowerDesigner 和 PDMReader 逆向生成 MySQL 数据字典

    下面提到的软件大家可以在下面的链接下载. 大家可以参考下面的操作录制视频来完成相关的操作. 使用 PowerDesigner 和 PDMReader 逆向生成 MySQL 数据字典.wmv_免费高速下 ...

  8. 【Java EE 学习 30】【闪回】【导入导出】【管理用户安全】【分布式数据库】【数据字典】【方案】

    一.闪回 1.可能的误操作 (1)错误的删除了记录 (2)错误的删除了表 (3)查询历史记录 (4)撤销已经提交了的事务. 2.对应着以上四种类型的误操作,有四种闪回类型 (1)闪回表:将表回退到过去 ...

  9. 数据字典生成工具之旅(5):DocX组件读取与写入Word

    由于上周工作比较繁忙,所以这篇文章等了这么久才写(预告一下,下一个章节正式进入NVelocity篇,到时会讲解怎么使用NVelocity做一款简易的代码生成器,敬请期待!),好了正式进入本篇内容. 这 ...

随机推荐

  1. PHP测试用例文档

    PHP接口测试用例和文档 PHP在过程中的测试 采用写一个简单html表单做一个简单的post测试 PHP接口测试文档 Alpha部分主要的接口文档可查看 接口文档 功能模块 接口 登录注册模块 验证 ...

  2. canvas beginPath()

    先举个简单的例子, var myCanvas = document.getElementById("myCanvas"); var context= myCanvas.getCon ...

  3. redis的 rdb 和 aof 持久化的区别 [转]

    aof,rdb是两种 redis持久化的机制.用于crash后,redis的恢复. rdb的特性如下: Code: fork一个进程,遍历hash table,利用copy on write,把整个d ...

  4. app开发遇到问题及解决

    1:ios and Android 差异input type=text 当用户点击input框时,弹出手机键盘,ios会遮挡输入框 解决办法: pswOnFocus = function(){ tar ...

  5. linux下不同服务器间数据传输(rcp,scp,rsync,ftp,sftp,lftp,wget,curl)(zz)

    linux下不同服务器间数据传输(rcp,scp,rsync,ftp,sftp,lftp,wget,curl) 分类: linux2011-10-10 13:21 8773人阅读 评论(1) 收藏 举 ...

  6. (转)__cdecl __fastcall与 __stdcall

    原帖 http://blog.sina.com.cn/s/blog_6b7c56870100l8rf.html __cdecl   __fastcall与   __stdcall 调用约定:  __c ...

  7. 开博了,hello world

    hello  world     hello  world    hello  world     hello  world   hello  world     hello  world    he ...

  8. 使用Application Insights 做分析

    Application Insights on Windows Desktop apps, services and worker roles : https://azure.microsoft.co ...

  9. android检测版本更新

    原理就是从服务器获取版本号和本得apk的版本号对比更新: //检查更新        Activity activity = this;        while(activity.getParent ...

  10. CAD 二次开发----- 块(一)

    1.块定义与块参照两个概念 块定义类似于模具,而块参照类似于模具浇筑出来的模型,在图形中只需用块定义来保存块的实际几何组成,而仅用插入点和比例因子来存储块定义,因为块参照的几何形状与快参照完全一样,仅 ...