首批通过分布式安全可靠测评,为关键业务系统打造
OBKV-HBase 过期数据删除
更新时间:2025-04-15 19:10:11
OBKV-HBase 实现了过期数据删除(TTL)的能力,本文介绍如何通过命令或周期任务删除过期数据。
注意
过期数据删除(TTL)功能仅限于 OceanBase KV 场景使用,SQL 场景下禁用,否则会导致不可预期的数据误删除问题。
背景信息
OBKV-HBase 提供了过期数据删除的功能,对于 HBase 表,用户也可以为每一个 Column Family 指定数据的存活时间(Time To Live)或者最大版本数(MaxVersions)。在定义好过期策略之后,用户可以通过命令或者设置周期性任务两种方式触发删除任务,从而减少存储空间占用。同时,对于 OBKV-HBase操作,OceanBase 数据库也会对过期数据进行过滤,以屏蔽过期数据的可见性。
说明
目前 OBKV-HBase 只支持表级别 TTL。
使用说明
由于 OceanBase 数据库使用了 LSM-Tree 架构(删除也是一个追加写的操作),即使通过 TTL 任务删除了过期数据,实际存储空间不仅有可能不降低,而且还可能增加,而最终存储空间的释放还是需要依靠 Major Compaction,因此建议配合 major freeze 同时使用,在 TTL 任务删除完成之后执行 major freeze,例如,可以通过设置 major_freeze_duty_time 在 kv_ttl_duty_duration 之后实现。
TTL 过期删除任务是一个后台低优先级任务,暂无法保证过期数据立即删除的能力,为了不对系统的性能造成较大影响,在任务的执行过程中如果遇到 MemStore 内存 MEMSTORE_USED 超过阈值 FREEZE_TRIGGER(可以通过视图 gv$ob_memstore 查看)的情况,会暂停当前任务的执行直到内存降低到阈值以下。同时,为了不影响系统的恢复流程,对于正常进行物理恢复的租户,TTL 任务同样也会暂停该租户 TTL 任务的执行,直到租户完成恢复。
TTL 表的定义
创建一张 Hbase 模型表 t1$cf1,并且定义 kv_attributes 为 {"Hbase": {"TimeToLive": 3600, "MaxVersions": 3}},表示每行数据的过期时间为 3600s,每行数据的最大版本数量为 3。
create table t1$cf1 (
K varbinary(1024),
Q varbinary(256),
T bigint,
V varbinary(1048576) NOT NULL,
primary key(K, Q, T))
kv_attributes ='{"Hbase": {"TimeToLive": 3600, "MaxVersions": 3}}'
partition by key(K) partitions 97
修改 Hbase 表 t1$cf1,移除 TimeToLive 属性,修改最大版本数量为 4。
alter table t1$cf1 kv_attributes ='{"Hbase": {"MaxVersions": 4}}';
移除 Hbase 表 t1$cf1 的过期属性。
alter table t1$cf1 kv_attributes ='{"Hbase": {}}';
TTL 任务的并行度
可以通过租户级配置项 ttl_thread_score 设置 TTL 工作线程数量,默认值为 2。
例如,修改 TTL 任务的并行度为 10:
alter system set ttl_thread_score = 10;
任务触发
触发 TTL 删除任务有两种方式,管控命令触发和周期性任务触发。
任务触发前需要打开租户的 TTL 任务开关。
ALTER SYSTEM SET enable_kv_ttl= true; // 默认值为 false
管控命令触发
登录到系统租户,并执行如下命令,触发所有租户的 TTL 任务。
ALTER SYSTEM trigger ttl;设置周期任务
登录到您需要执行 TTL 任务的租户,执行如下命令设置租户每天 TTL 任务的触发时间。
alter system set kv_ttl_duty_duration = '[22:00:00, 24:00:00]'; // 默认值为 "",表示不触发周期性 TTL 任务
登录到系统租户,并执行如下系统命令,可以挂起、恢复和取消正在执行的 TTL 任务。
ALTER SYSTEM suspend ttl; // 挂起当前正在执行的 TTL 任务
ALTER SYSTEM resume ttl; // 恢复当前挂起的 TTL 任务
ALTER SYSTEM cancel ttl; // 取消正在执行的 TTL 任务
TTL 命令只在用户租户或系统租户下执行有效。在用户租户下执行,只能管控本租户的 TTL 任务;在系统租户下执行,可以管控所有用户的 TTL 任务。
下面以 trigger 命令为例,其他命令 suspend/resume/cancel 的作用租户行为一致。
| 租户 | 命令 | 语义 |
|---|---|---|
| 系统租户 | alter system trigger ttl |
所有用户租户 |
| 系统租户 | alter system trigger ttl tenant = all |
所有用户租户 |
| 系统租户 | alter system trigger ttl tenant = all_user |
所有用户租户 |
| 系统租户 | alter system trigger ttl tenant = obkv |
obkv 租户 |
| 系统租户 | alter system trigger ttl tenant = obkv1, obkv2 |
用户租户 obkv1, obkv2 |
| 用户租户 | alter system trigger ttl |
本租户 |
查看任务状态
通过视图可以查看当前以及历史 TTL 任务的状态和相关信息,与 TTL 任务相关的视图有四张。
| 视图名称 | 视图作用 |
|---|---|
| DBA_OB_KV_TTL_TASKS | 查看当前租户正在执行的 TTL 任务 |
| DBA_OB_KV_TTL_TASK_HISTORY | 查看当前租户的历史 TTL 任务 |
| CDB_OB_KV_TTL_TASKS | 系统租户下查看所有租户正在执行的 TTL 任务 |
| CDB_OB_KV_TTL_TASK_HISTORY | 系统租户下查看所有租户的历史 TTL 任务 |
视图 DBA_OB_KV_TTL_TASKS 和 DBA_OB_KV_TTL_TASK_HISTORY 字段说明:
| 字段 | 说明 |
|---|---|
| TABLE_NAME | 表名 |
| TABLE_ID | 表 ID |
| TABLET_ID | Tablet ID |
| TASK_ID | 任务 ID,从 1 开始 |
| START_TIME | 任务开始时间 |
| END_TIME | 任务结束时间 |
| TRIGGER_TYPE | 任务触发类型,包括 PERIODIC 和 USER 两种 |
| STATUS | 任务当前状态,见任务表状态说明 |
| TTL_DEL_CNT | 关系表删除的记录数量 / Hbase 表基于 TimeToLive 删除的记录数量 |
| MAX_VERSION_DEL_CNT | Hbase 表基于 MaxVersions 删除的记录数量 |
| SCAN_CNT | 任务扫描的记录数量 |
| RET_CODE | 任务返回码 |
视图 CDB_OB_KV_TTL_TASKS 和 CDB_OB_KV_TTL_TASK_HISTORY 字段说明:
说明
相比较 DBA 视图,只多了一个租户 ID。
| 字段 | 说明 |
|---|---|
| TENANT_ID | 租户 ID |
| TABLE_NAME | 表名 |
| TABLE_ID | 表 ID |
| TABLET_ID | Tablet ID |
| TASK_ID | 任务 ID,从 1 开始 |
| START_TIME | 任务开始时间 |
| END_TIME | 任务结束时间 |
| TRIGGER_TYPE | 任务触发类型,包括 PERIODIC 和 USER 两种 |
| STATUS | 任务当前状态,见任务表状态说明 |
| TTL_DEL_CNT | 关系表删除的记录数量 / Hbase 表基于 TimeToLive 删除的记录数量 |
| MAX_VERSION_DEL_CNT | Hbase 表基于 MaxVersions 删除的记录数量 |
| SCAN_CNT | 任务扫描的记录数量 |
| RET_CODE | 任务返回码 |
过期数据的可见性
如果使用 OBKV (Table/Hbase)接口对某条记录进行操作,但是该条记录已经过期,这个时候的表现和该条记录不存在保持一致。例如,关系表中存在一条主键为 k1 的过期记录,这个时候再插入一条主键为 k1 的记录会成功,而不是报主键冲突。
| 操作 | 过期 | 返回码 | affected rows | 其他 |
|---|---|---|---|---|
| insert | N | -5024 OB_ERR_PRIMARY_KEY_DUPLICATE |
0 | |
| insert | Y | 0 OB_SUCCESS |
1 | |
| delete | N | 0 OB_SUCCESS |
1 | |
| delete | Y | 0 OB_SUCCESS |
0 | |
| update | N | 0 OB_SUCCESS |
1 | |
| update | Y | 0 OB_SUCCESS |
0 | |
| replace | N | 0 OB_SUCCESS |
2 | |
| replace | Y | 0 OB_SUCCESS |
1 | |
| insert_or_update | N | 0 OB_SUCCESS |
1 | |
| insert_or_update | Y | 0 OB_SUCCESS |
1 | |
| increment | N | 0 OB_SUCCESS |
1 | |
| increment | Y | 0 OB_SUCCESS |
1 | 除了 increment 列其他列会被写成默认值 |
| append | N | 0 OB_SUCCESS |
1 | |
| append | Y | 0 OB_SUCCESS |
1 | 除了 append 列其他列会被写成默认值 |
| query/get | N | 0 OB_SUCCESS |
/ | 成功读到数据 |
| query/get | Y | 0 OB_SUCCESS |
/ | 读不到数据 |
说明
SQL 接口暂时不会对过期数据进行屏蔽,在过期数据被删除任务清理之前,过期数据都是可见的。
任务状态说明
对于每一个租户的 TTL 任务,在实际执行时,会被拆分成每个 TTL 表的 Tablet 级别任务,正在执行的租户任务和其 Tablet 任务都会被记录在任务表中,通过任务视图可以查看,历史分区任务会被移动到历史表中,通过历史视图可以查看。
注意
租户级任务的 TABLE_NAME 为 NULL,TABLET_ID、TABLE_ID 均为 -1。
- 在任务视图 DBA_OB_KV_TTL_TASKS 和 CDB_OB_KV_TTL_TASKS 中,有两类任务:租户级任务和 Tablet 级任务,对应两类不同状态。
- 在历史任务视图 DBA_OB_KV_TTL_TASK_HISTORY 和 CDB_OB_KV_TTL_TASK_HISTORY 中,保存历史租户级任务和 Tablet 任务记录。
Tablet 任务状态:
| 任务状态 | 说明 |
|---|---|
| PREPARED | 准备状态,还未开始删除过期数据 |
| RUNNING | 运行状态,正在删除该分区过期数据 |
| PENDING | 挂起状态,可以通过命令恢复执行 |
| CANCELED | 取消状态,无法恢复执行 |
| FINISHED | 完成状态,待移动到历史表中 |
| INVALID | 非法状态 |
租户任务状态:
| 任务状态 | 说明 |
|---|---|
| RS_TRIGGERING | 表示租户 TTL 任务正在执行中 |
| RS_SUSPENDING | 表示租户 TTL 任务已经挂起 |
| RS_CANCELING | 表示租户 TTL 任务已经取消 |
| RS_MOVING | 表示正在移动所有的 TTL 任务记录到历史表 |
| INVALID | 非法状态 |
设置历史任务清理周期
为了避免 TTL 历史任务堆积造成不必要的存储空间浪费,可以通过 kv_ttl_history_recycle_interval 配置项设置租户的历史 TTL 任务记录的保存时长(默认为 7 天)。
ALTER SYSTEM SET kv_ttl_history_recycle_interval= '30d'; // 设置自动清理超过 30 天的历史 TTL 任务记录
示例:定时删除过期数据
创建一个 Hbase 模型表。
create table t1$cf1 ( K varbinary(1024), Q varbinary(256), T bigint, V varbinary(1048576) NOT NULL, primary key(K, Q, T)) kv_attributes ='{"Hbase": {"TimeToLive": 3600, "MaxVersions": 3}}' partition by key(K) partitions 3;模拟 OBKV-HBase 插入数据。
实际插入数据过程请参考 OBKV-HBase 客户端使用介绍。
```sql
INSERT INTO t1$cf1 VALUES
("row1", "cq1", -truncate(time_to_usec(date_sub(now(), interval +1 hour))/1000, 0), "del"),
("row1", "cq1", -truncate(time_to_usec(now())/1000, 0), "no del"),
("row2", "cq1", -truncate(time_to_usec(date_sub(now(), interval +1 hour))/1000, 0), "del"),
("row2", "cq1", -truncate(time_to_usec(now())/1000, 0), "no del"),
("row3", "cq1", -truncate(time_to_usec(date_sub(now(), interval +1 hour))/1000, 0), "del"),
("row3", "cq1", -truncate(time_to_usec(now())/1000, 0), "no del"),
("row4", "cq1", -truncate(time_to_usec(date_sub(now(), interval +1 hour))/1000, 0), "del"),
("row4", "cq1", -truncate(time_to_usec(now())/1000, 0), "no del");
```
设置租户每日 TTL 任务时间并打开定时任务开关。
ALTER SYSTEM SET enable_kv_ttl= true; // 打开 TTL 任务 ALTER SYSTEM SET kv_ttl_duty_duration = '[00:00:00, 23:59:59]'; // 从 0 点开始,会尝试触发一次 TTL 任务查看任务执行状态。
查看当前任务(执行结果取决于实际任务执行状态)。
obclient> select * from oceanbase.dba_ob_kv_ttl_tasks;返回结果如下:
+------------+----------+-----------+---------+----------------------------+----------------------------+--------------+---------------+-------------+---------------------+----------+------------+ | TABLE_NAME | TABLE_ID | TABLET_ID | TASK_ID | START_TIME | END_TIME | TRIGGER_TYPE | STATUS | TTL_DEL_CNT | MAX_VERSION_DEL_CNT | SCAN_CNT | RET_CODE | +------------+----------+-----------+---------+----------------------------+----------------------------+--------------+---------------+-------------+---------------------+----------+------------+ | NULL | -1 | -1 | 1 | 2023-09-28 11:35:02.695292 | 2023-09-28 11:35:17.720627 | PERIODIC | RS_TRIGGERING | 0 | 0 | 0 | OB_SUCCESS | | t1$cf1 | 500002 | 200001 | 1 | 2023-09-28 11:35:06.612708 | 2023-09-28 11:35:06.612708 | PERIODIC | PREPARED | 0 | 0 | 0 | OB_SUCCESS | | t1$cf1 | 500002 | 200002 | 1 | 2023-09-28 11:35:06.612711 | 2023-09-28 11:35:06.612711 | PERIODIC | PREPARED | 0 | 0 | 0 | OB_SUCCESS | | t1$cf1 | 500002 | 200003 | 1 | 2023-09-28 11:35:06.612712 | 2023-09-28 11:35:06.612712 | PERIODIC | PREPARED | 0 | 0 | 0 | OB_SUCCESS | +------------+----------+-----------+---------+----------------------------+----------------------------+--------------+---------------+-------------+---------------------+----------+------------+ 4 rows in set查看历史任务(执行结果取决实际任务执行状态)。
obclient> select * from oceanbase.dba_ob_kv_ttl_task_history;返回结果如下:
+------------+----------+-----------+---------+----------------------------+----------------------------+--------------+----------+-------------+---------------------+----------+------------+ | TABLE_NAME | TABLE_ID | TABLET_ID | TASK_ID | START_TIME | END_TIME | TRIGGER_TYPE | STATUS | TTL_DEL_CNT | MAX_VERSION_DEL_CNT | SCAN_CNT | RET_CODE | +------------+----------+-----------+---------+----------------------------+----------------------------+--------------+----------+-------------+---------------------+----------+------------+ | NULL | -1 | -1 | 1 | 2023-09-28 11:35:02.695292 | 2023-09-28 11:35:17.720627 | PERIODIC | FINISHED | 0 | 0 | 0 | OB_SUCCESS | | t1$cf1 | 500002 | 200001 | 1 | 2023-09-28 11:35:06.612708 | 2023-09-28 11:35:11.634029 | PERIODIC | FINISHED | 1 | 0 | 2 | OB_SUCCESS | | t1$cf1 | 500002 | 200002 | 1 | 2023-09-28 11:35:06.612711 | 2023-09-28 11:35:11.632463 | PERIODIC | FINISHED | 1 | 0 | 2 | OB_SUCCESS | | t1$cf1 | 500002 | 200003 | 1 | 2023-09-28 11:35:06.612712 | 2023-09-28 11:35:11.627921 | PERIODIC | FINISHED | 2 | 0 | 4 | OB_SUCCESS | +------------+----------+-----------+---------+----------------------------+----------------------------+--------------+----------+-------------+---------------------+----------+------------+ 4 rows in set
查看当前 Hbase 模型表中的数据。
obclient> select * from t1$cf1;返回结果如下:
+------+-----+----------------+--------+ | K | Q | T | V | +------+-----+----------------+--------+ | row3 | cq1 | -1695872081000 | no del | | row4 | cq1 | -1695872081000 | no del | | row1 | cq1 | -1695872081000 | no del | | row2 | cq1 | -1695872081000 | no del | +------+-----+----------------+--------+ 4 rows in set