RocksDB是facebook基于LevelDB实现的,目前为facebook内部大量业务提供服务。经过facebook大量工作,将RocksDB作为MySQL的一个存储引擎移植到MySQL,称之为MyRocks。 经过两年的发展,MyRocks已经比较成熟(RC阶段),现已进入了facebook MySQL的主分支了。MyRocks是开源的,参见[git](https://github.com/facebook/MySQL-5.6) 。 下面对MyRocks做一个简单介绍,不涉及源码。 ## RocksDB与innodb的比较 * innodb空间浪费, B tree分裂导致page内有较多空闲,page利用率不高。innodb现有的压缩效率也不高,压缩以block为单位,也会造成浪费。 * 写入放大:innodb 更新以页为单位,最坏的情况更新N行会更新N个页。RocksDB append only方式 另外,innodb开启double write也会增加写入。 * RocksDB对齐开销小:SST file (默认2MB)需要对齐,但远大于4k, RocksDB_block_size(默认4k) 不需要对齐,因此对齐浪费空间较少 * RocksDB索引前缀相同值压缩存储,节省空间 * RocksDB占总数据量90%的最底层数据,行内不需要存储系统列seqid (innodb聚簇索引列包含trxid,roll_ptr等信息) 来看看facebook的测试数据 * 数据空间对比 ![screenshot](http://img4.tbcdn.cn/L1/461/1/8c5ab67bf3d062668c41ef6b61b211e1db5e7166) * QPS ![screenshot](http://img3.tbcdn.cn/L1/461/1/bcc894baeec3236a474aa5be4afc2c1a57266c91) * 写入放大对比 ![screenshot](http://img4.tbcdn.cn/L1/461/1/4ec40d4a6ef27c3eb46b206e864e2e94b5b34bde) ## 数据字典 数据字段信息保存在System Column Family (System CF) “system“中 数据字段信息包括: * 表信息,表名和index id的映射 * 索引信息,索引元数据信息和column family id。column family和index的对应关系 1:N * column family,一些标记,比如reverse属性等 * binlog信息 * 统计信息,每个SST file都自带统计信息(行数、实际大小等),在flush或compaction时更新统计信息,同时统计信息会汇总到数据字典统计信息表中。 以上信息可以通过information_schema查看,如RocksDB_ddl,RocksDB_index_file_map等 ## 记录格式 RocksDB的行以key value的形式存储,和innodb类似,记录格式主键和二级索引也有区别 ![screenshot](http://img3.tbcdn.cn/L1/461/1/d0069515c04809a449eda659386afbe966e0d1df) ## 事务与锁 MyRocks也是基于行锁,锁信息都保存在内存中。 MyRocks也支持MVCC,MVCC通过快照的方式实现,类似于PostgreSQL。 MyRocks目前只支持两种隔离级别,RC和RR。 RR表现和innodb并不一样,RocksDB 的快照不是在事务开始的时候建立,而是延迟到第一次读的时候建立. 以下client1 MyRocks返回的是2,innodb返回1 ~~~ <client 1> <client 2> CREATE TABLE t1(pk INT PRIMARY KEY); INSERT INTO t1 VALUES(1); SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; BEGIN INSERT INTO t1 VALUES(2); SELECT COUNT(*) FROM t1; // MyRocks返回的是2,innodb返回1 ~~~ RC表现也不一样,事务1大更新多行过程中,其他事务也可以更新事务还未更新到的行,事务1再更新时会失败。 ## 复制 MyRocks也是通过binlog方式复制,由于binlog与RocksDB之间没有xa,异常crash可能丢数据,所以,MyRocks主备环境建议开启semi-sync. 由于gap lock支持不健全(仅primary key上支持), 使用statement方式复制会导致不一致,所有MyRocks建议使用行级复制。 ## 备份恢复 支持MySQLdumup逻辑备份 ~~~ #内部会执行以下语句 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; START TRANSACTION WITH CONSISTENT RocksDB SNAPSHOT; ~~~ 同时有自动的物理备份工具MyRocks_hotbackup,但还不支持备份innodb; 也不支持增量备份。MyRocks_hotbackup支持流式备份 ~~~ MyRocks_hotbackup--user=root --port=3306 --checkpoint_dir=/data/backup --stream=xbstream| ssh$dst‘xbstream–x /data/backup’ #内部建立硬链接方式备份数据SST files,checkpoint多次更新,只备份新的SST files, 因此WAL日志很少,恢复时apply log时间很短 SET GLOBAL RocksDB_create_checkpoint= /path/to/backup ~~~ ## 一些优化 * bloom filter bloom filter一般适用于等值查询 bloom filter信息存储在SST files中,大概占用2~3%的空间 如果大量查询返回空集建议开启bloom filter,如果结果每次都在最底层找到,可以设置optimize_filters_for_hits=true关闭bloom filter以节省空间。 * 数据加载 数据加载时可以忽略唯一性约束检查,分段自动提交,停写wal等。 以下是推荐的数据加载时的参数配置 ~~~ rocksdb_skip_unique_check=1 rocksdb_commit_in_the_middle=1 rocksdb_write_disable_wal=1 rocksdb_max_background_flushes=40 rocksdb_max_background_compactions=40 rocksdb_default_cf_options=(in addition to existing parameters); write_buffer_size=128m;level0_file_num_compaction_trigger=4;level0_slowdown_writes_trigger=256;level0_stop_writes_trigger=256;max_write_buffer_number=16;memtable=vector:1024 rocksdb_override_cf_options=(in addition to existing parameters);__system__={memtable=skip_list:16} ~~~ * Reverse column families MyRocks擅长正向扫描,为了提高逆向扫描(ORDER BY DESC)的性能,MyRocks支持了Reverse column families。 在建表可以指定column family的reverse属性。 * singleDelete 如果key不会重复put, delete操作可以直接删除put,而不是标记删除。singleDelete可以提供查询效率。 ## 一些限制 MyRocks目前有以下一些限制 * 不支持分区表,Online ddl,外键,全文索引,空间索引,表空间transport * gap lock支持不健全(仅primary key上支持), 使用statement方式复制会导致不一致 * 不支持select … in share mode * 大小写敏感,不支持*_bin collation * binlog与RocksDB之间没有xa,异常crash可能丢数据。所以,MyRocks一般开启semi-sync. * 不支持savepoint * order by 不比较慢 * 不支持MRR * 暂不支持O_DIRECT * innodb和RocksDB混合使用还不稳定