laravel5.6 使用指定字段作为key_MyRocks TTL使用姿势及Bugfix

一些业务场景是经过一段时间后删除过期的数据,MyRocks提供了TTL可以满足该场景。MyRocks 通过Compaction回收过期的数据。本文介绍MyRocks TTL使用姿势以及Bugfix。

TTL 通过 table comment 定义,有两种形式:

CREATE TABLE t1 (a INT, b INT, c INT, PRIMARY KEY (a), KEY(b)) ENGINE=ROCKSDB COMMENT "ttl_duration=3600;";

CREATE TABLE t2 (a INT, b INT, c INT, ts BIGINT UNSIGNED NOT NULL, PRIMARY KEY (a), KEY(b)) ENGINE=ROCKSDB COMMENT "ttl_duration=3600;ttl_col=ts;";

ttl_duration: 指定过期时间,单位是秒

ttl_col : 指定过期时间列,列的数据类型必须是 bigint unsigned not null, 不能是datetime类型。

表t1没有指定ttl_col,record插入的时间作为created time 会记录在record中,注意更新(update)此记录不会更新created time。表t2 显式指定了ttl_col,created time 直接从ttl_col列获取。

MyRocks 在读数据时会判断表是否有TTL定义,是否开启了rocksdb_enable_ttl_read_filtering(默认是开启的),如果都满足则会读取created time,判断是否过期。

实际使用中还碰到了一个TTL的bug,该bug是由Percona小伙伴提出来的,我们分析修掉了该Bug,如果表定义了TTL,并且有varchar字段,执行一些聚合查询会导致mysqld crash。重现该bug的方法如下:

CREATE TABLE `t1` (
`a` bigint(20) NOT NULL,
`b` varchar(10) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`u` bigint(20) unsigned NOT NULL,
`d` bigint(20) DEFAULT NULL,
PRIMARY KEY (`a`,`b`),
KEY `d` (`d`)
) ENGINE=ROCKSDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='ttl_duration=1000;ttl_col=u';
INSERT INTO t1 VALUES (100, 'aaabbb', UNIX_TIMESTAMP(), 200);
EXPLAIN SELECT COUNT(*) FROM t1;
SELECT COUNT(*) FROM t1;

执行以上语句会导致mysqld crash,主要原因是在解析二级索引元组的时候忽略了TTL隐藏字段。如果表没有定义TTL,二级索引record的KV格式如下:

key: index number, NULL-flag, M(c), M(a)

value: empty or restore data

如果表定义了TTL字段,二级索引record的KV格式如下:

key: index number, NULL-flag, M(c), M(a)

value: timestamp or restore data

因为RocksDB存储的是KV格式的数据,MyRocks handler层负责把行记录格式的数据转成KV格式的数据,这个过程叫做pack,在查询的时候,再把底层KV格式的数据转换成行格式,这个过程叫做unpack。如果行记录中有特殊字段比如varchar、blob等,value还会存储unpack info,主要是为了能恢复出原来的varchar、blob。

该bug主要是在unpack_record函数中出错,

1f6de6179850b900f97454a50618b553.png

reader 保存二级索引KV中的key, unp_reader保存二级索引KV中的value,

f8ef83559064e7f72c339d2e08752ebd.png

注释中也说明了会按照unpack data 、checksum的顺序解析,但是如果表定义了TTL,value开始的8字节存储的是TTL时间戳,这么解析就出错了。解决的办法也很简单,就是要跳过TTL时间戳,

7f6213ea2542981b78229291ec606ebb.png

参考链接:

1、官方wiki: https://github.com/facebook/mysql-5.6/wiki/Time-to-Live-(TTL)

2、bug issue: https://github.com/facebook/mysql-5.6/issues/896

3、bug patch : https://github.com/facebook/mysql-5.6/pull/898

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值