---
title: "OBKV-Table 过期数据删除 - OceanBase 数据库 V4.4.2 | OceanBase 文档中心"
description: OBKV-Table 过期数据删除 OBKV-Table 提供了过期数据删除的功能，用户可以通过定义、配置和触发过期策略，减少存储空间占用。同时，OBKV-Table 也会对过期数据进行过滤，以屏蔽过期数据的可见性。本文介绍如何通过命令或周期任务删除过期数据。 注意 过期数据删除（TTL）功能仅限于 OceanBas…
---
切换语言

- 中文站 - 简体中文
- International - English
- 日本站 - 日本語

文档反馈![](https://mdn.alipayobjects.com/huamei_22khvb/afts/img/A*P8CuR4UJ_FkAAAAAAAAAAAAADiGDAQ/original) OceanBase 数据库KV 型 - V 4.4.2 LTS

# OBKV-Table 过期数据删除

更新时间：2026-07-23 19:56:22

[编辑](https://github.com/oceanbase/oceanbase-kv/edit/V4.4.2/zh-CN/100.obkv-table/700.obkv-table-reference/290.obkv-table-ttl.md)  

OBKV-Table 提供了过期数据删除的功能，用户可以通过定义、配置和触发过期策略，减少存储空间占用。同时，OBKV-Table 也会对过期数据进行过滤，以屏蔽过期数据的可见性。本文介绍如何通过命令或周期任务删除过期数据。

#### 注意

过期数据删除（TTL）功能仅限于 OceanBase KV 场景使用，SQL 场景下禁用，否则会导致不可预期的数据误删除问题。

## 使用说明

TTL 功能的基本使用流程如下：

1. 开启 TTL 功能：设置 `enable_kv_ttl = true` 开启租户的 TTL 任务开关。
 2. 定义 TTL 表：创建表时指定 TTL 属性，或对已有表添加 TTL 属性。支持修改/移除 TTL 属性。
 3. 触发删除任务：通过手动命令或设置周期任务触发过期数据删除。支持暂停/恢复/取消正在执行的任务。
 4. 查看任务状态：通过系统视图监控任务执行情况。

下面详细展开介绍。

### 第一步：开启 TTL 功能

开启 TTL 功能需要设置租户级配置项 `enable_kv_ttl` 为 `true`。

```sql
ALTER SYSTEM SET enable_kv_ttl= true; -- 租户级配置项，默认值为 false

```

### 第二步：定义 TTL 表

表的 TTL 属性通过 `COLUMN_NAME + INTERVAL NUM TTL_UNIT` 式定义，其中:

- `COLUMN_NAME`：表中的已定义属性，类型为 TIMESTAMP 或 DATETIME。
 - `+ INTERVAL`：固定部分。
 - `NUM`：过期时间的整型。
 - `TTL_UNIT`：可以是 `SECOND`, `MINUTE`, `HOUR`, `DAY`, `MONTH`, `YEAR` 中的任意一种。

如果是创建新的 TTL 关系表 t1，设置每行数据在 12 小时后会过期，可以通过以下语句创建：

```sql
CREATE TABLE t1 (
  a INT PRIMARY KEY,
  b TIMESTAMP DEFAULT current_timestamp ON UPDATE current_timestamp)
TTL (b + INTERVAL 12 HOUR);

```

如果是变更已有表 t1 的 TTL 属性，修改过期时间为 1 天，可以通过以下语句变更：

```sql
ALTER TABLE t1 TTL (b + INTERVAL 1 DAY);

```

如果是移除表 t1 的 TTL 属性，可以通过以下语句移除：

```sql
ALTER TABLE t1 REMOVE TTL;

```

### 第三步：任务触发

触发 TTL 删除任务有两种方式：

- 管控命令触发：需登录到系统租户，用于触发所有租户的 TTL 任务。除了触发任务，系统租户还支持暂停、恢复和取消正在执行的 TTL 任务。
 - 周期性任务触发：需登陆到您需要执行 TTL 任务的用户租户，设置该用户租户每天的 TTL 任务触发时间。

TTL 命令只在用户租户或系统租户下执行有效。在用户租户下执行，只能管控本租户的 TTL 任务；在系统租户下执行，可以管控所有用户的 TTL 任务。

    管控命令触发示例   周期性任务触发示例

登录到系统租户，并执行如下命令，触发所有租户的 TTL 任务。

```sql
ALTER SYSTEM TRIGGER TTL;

```

暂停正在执行的 TTL 任务，命令如下：

```sql
ALTER SYSTEM SUSPEND TTL;

```

恢复暂停的 TTL 任务，命令如下：

```sql
ALTER SYSTEM RESUME TTL;

```

取消正在执行的 TTL 任务，命令如下：

```sql
ALTER SYSTEM CANCEL TTL;

```

登录到您需要执行 TTL 任务的租户，执行如下命令设置租户每天 TTL 任务的触发时间。

```sql
-- 默认值为 ""，表示不触发周期性 TTL 任务
ALTER SYSTEM SET kv_ttl_duty_duration = '[22:00:00, 24:00:00]';

```

### 第四步：查看任务状态

通过以下视图可以查看当前以及历史 TTL 任务的状态和相关信息：

| 视图名称 | 视图作用 |
| --- | --- |
| [DBA_OB_KV_TTL_TASKS](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000003979246) | 查看当前租户正在执行的 TTL 任务 |
| [DBA_OB_KV_TTL_TASK_HISTORY](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000003979178) | 查看当前租户的历史 TTL 任务 |
| [CDB_OB_KV_TTL_TASKS](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000003978398) | 系统租户下查看所有租户正在执行的 TTL 任务，比 DBA 视图多了 `TENANT_ID` 列 |
| [CDB_OB_KV_TTL_TASK_HISTORY](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000003978661) | 系统租户下查看所有租户的历史 TTL 任务，比 DBA 视图多了 `TENANT_ID` 列 |

#### 任务状态说明

TTL 任务分为租户级任务和 Tablet 级任务两类，对应不同的状态，均可在任务视图 `DBA_OB_KV_TTL_TASKS` 和 `CDB_OB_KV_TTL_TASKS` 以及历史任务视图 `DBA_OB_KV_TTL_TASK_HISTORY` 和 `CDB_OB_KV_TTL_TASK_HISTORY` 中查看。

#### 注意

租户级任务的 `TABLE_NAME` 为 `NULL`，`TABLET_ID`、`TABLE_ID` 均为 `-1`。

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 天）。

例如，设置自动清理超过 30 天的历史 TTL 任务记录，命令如下：

```sql
ALTER SYSTEM SET kv_ttl_history_recycle_interval= '30d';

```

## 性能优化

### 设置并行度

可以通过租户级配置项 `ttl_thread_score` 设置 TTL 任务的工作线程数量，默认值为 2。

例如，修改 TTL 任务的工作线程数量为 10：

```sql
ALTER SYSTEM SET ttl_thread_score = 10;

```

### 索引扫描

TTL（Time To Live）支持通过索引扫描来提升过期数据清理的效率。在默认情况下，TTL 任务需对全表进行主键扫描并读取每一行数据来判断是否过期，这会带来较高的 I/O 开销。通过为过期列建立本地索引，并在 TTL 任务中指定使用该索引，只需扫描索引即可判断数据是否过期，从而减少无效的数据读取并显著提升清理速度。

在创建表时，通过属性参数 `KV_ATTRIBUTES` 的 `TTLScanIndex` 子参数指定索引名称来启用索引扫描，语法如下：

```sql
-- 实际使用中，$index_name 需要替换为索引名称
CREATE TABLE table_name (
  ...
) TTL (ttl_column + INTERVAL ...)
KV_ATTRIBUTES = '{"TTLScanIndex": "$index_name"}';

```

这里给出几个不同场景的示例：

    包含过期列的本地索引   冗余存储过期列的本地索引   后建带过期列的本地索引

示例 1 展示了 TTL 任务使用包含过期列的本地索引，来提升过期数据清理的效率：

```sql
CREATE TABLE test_ttl_with_index (
    a INT PRIMARY KEY,
    b TIMESTAMP DEFAULT current_timestamp ON UPDATE current_timestamp,
    c VARCHAR(128),
    INDEX idx(b) LOCAL
) TTL (b + INTERVAL 12 HOUR)
KV_ATTRIBUTES = '{"TTLScanIndex": "idx"}';

```

说明：

- 表使用 `b` 列作为 TTL 列，过期时间为 12 小时。
 - 通过 `TTLScanIndex` 指定使用 `idx` 索引进行扫描。
 - `idx` 索引建立在 TTL 列 `b` 上，可以高效定位过期数据。

当使用 OBKV-Table 的堆表模型时，一般会创建唯一索引作为唯一键，可以将过期列冗余存储在唯一索引上，TTL 任务指定该索引进行过期数据扫描。示例 2 展示了如何创建一个堆表，将过期列冗余存储在唯一索引上，并使用唯一索引进行过期数据扫描：

```sql
CREATE TABLE test_ttl_storing_index (
    pagerowkey VARCHAR(1024) NOT NULL,
    request LONGTEXT DEFAULT NULL,
    rawpage LONGBLOB NOT NULL,
    pagecode VARCHAR(1024) NOT NULL,
    timestamp BIGINT(20) NOT NULL,
    _expire_ts TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    -- 将 _expire_ts 冗余存储在唯一索引 u_idx_pagerowkey 上
    UNIQUE INDEX u_idx_pagerowkey (pagerowkey) STORING (_expire_ts)
) ORGANIZATION = HEAP DEFAULT CHARSET = utf8mb4
TTL (_expire_ts + INTERVAL 1 DAY)
-- 使用唯一索引 u_idx_pagerowkey 进行过期数据扫描
KV_ATTRIBUTES = '{"TTLScanIndex": "u_idx_pagerowkey"}';

```

说明：

- 通过 `STORING (_expire_ts)` 将 TTL 列 `_expire_ts` 冗余存储在唯一索引 `u_idx_pagerowkey` 上，避免在 TTL 任务中进行回表查询。

示例 3 展示了如何先创建表，后续通过 `ALTER TABLE` 添加索引 `idx3` 并启用索引扫描：

```sql
-- 创建表（初始不使用索引扫描）
CREATE TABLE test_ttl_with_index_6 (
    a INT PRIMARY KEY,
    b TIMESTAMP DEFAULT current_timestamp ON UPDATE current_timestamp,
    c VARCHAR(128),
    INDEX idx(b) LOCAL,
    INDEX idx2(c) LOCAL
) TTL (b + INTERVAL 12 HOUR);

-- 添加索引并启用索引扫描
ALTER TABLE test_ttl_with_index_6 ADD INDEX idx3(b, c);
ALTER TABLE test_ttl_with_index_6 SET KV_ATTRIBUTES = '{"TTLScanIndex": "idx3"}';

```

说明：

- 通过 `ALTER TABLE` 添加索引 `idx3` 并启用索引扫描。
 - 通过 `KV_ATTRIBUTES` 指定使用索引 `idx3` 进行过期数据扫描。

## 注意事项

### 过滤变更日志

#### 注意

该功能从 V4.4.2 BP1 版本开始支持，需要搭配 V4.4.2 BP1 及以上版本的 liboblog 使用。

TTL 任务在删除过期数据时会产生大量变更日志（Change Log，CLOG）。默认情况下，CDC（liboblog）会正常捕获并消费这些变更日志，再同步给下游组件。在过期数据量较大的场景下，TTL 删除过期数据产生的大量日志会给 CDC 链路带来额外的处理压力及资源开销。

为减轻 CDC 链路资源压力，可开启 CDC 侧 TTL 变更日志过滤能力（`filter_ttl_delete_log`）。开启后，TTL 任务产生的变更日志会被 CDC 过滤，不再向下游输出。默认不启用过滤，即 TTL 变更日志会被 CDC 正常消费；开启过滤后，仅影响 TTL 任务变更日志，不改变 TTL 任务本身的执行逻辑。

### 过期数据的可见性

如果使用 OBKV-Table 接口对某条记录进行操作，但是该条记录已经过期，这个时候的表现和该条记录不存在保持一致。例如，关系表中存在一条主键为 `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 过期删除任务是一个后台低优先级任务，暂无法保证过期数据立即删除。为了不对系统性能造成较大影响，在以下情况下任务会自动暂停：

- 内存压力：当 MemStore 内存 `MEMSTORE_USED` 超过阈值 `FREEZE_TRIGGER` 时，任务会暂停执行，直到内存降低到阈值以下。可通过视图 `GV$OB_MEMSTORE` 查看内存使用情况。
 - 物理恢复期间：对于正在进行物理恢复的租户，TTL 任务会暂停执行，直到租户完成恢复。

### 存储空间释放

由于 OceanBase 数据库采用 LSM-Tree 架构，删除操作本质上是一次追加写入（写入删除标记）。因此，TTL 任务删除过期数据后，实际存储空间不会立即释放，甚至可能暂时增加。存储空间的最终释放依赖于 Major Compaction 过程。

为了确保存储空间能够及时释放，建议将 TTL 任务与 Major Freeze 配合使用：

1. 设置 TTL 任务的执行时间窗口（`kv_ttl_duty_duration`）。
 2. 将 Major Freeze 的执行时间（`major_freeze_duty_time`）设置在 TTL 任务窗口之后。

这样可以在 TTL 任务完成后自动触发 Major Compaction，从而释放存储空间。

## 完整示例

1. 启用 TTL 功能

   ```sql
   ALTER SYSTEM SET enable_kv_ttl= true;

   ```
 2. 创建一个 TTL 关系表，并定义每条记录在 c + 10s 之后过期。

   ```sql
   CREATE TABLE ttl_table(a VARCHAR(1024) PRIMARY KEY,
     b VARCHAR(1024),
     c TIMESTAMP)
     TTL(c + INTERVAL 10 SECOND) PARTITION BY KEY(a) PARTITIONS 3;

   ```
 3. 插入数据（可以使用 OBKV-Table/SQL，采用 OBKV-Table 接口插入数据，详细操作，请参见 [客户端简介与使用说明](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005280346)）。

   ```sql
   INSERT INTO ttl_table VALUES("k1", "hello obkv", now());
   INSERT INTO ttl_table VALUES("k2", "hello obkv", now());
   INSERT INTO ttl_table VALUES("k3", "hello obkv", now());

   ```
 4. 等待 10s 之后，执行命令触发 TTL 任务执行。

   ```sql
   ALTER SYSTEM TRIGGER TTL; -- 从 0 点开始，会尝试触发一次 TTL 任务

   ```
 5. 查看任务执行状态。

   ```shell
   obclient> SELECT * FROM OCEANBASE.DBA_OB_KV_TTL_TASKS;

   ```

   返回结果如下：

   ```shell
   +------------+----------+-----------+---------+----------------------------+----------------------------+--------------+---------------+-------------+---------------------+----------+------------+
   | 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   |
   +------------+----------+-----------+---------+----------------------------+----------------------------+--------------+---------------+-------------+---------------------+----------+------------+
   | ttl_table  |   500002 |    200003 |       1 | 2023-09-27 23:31:30.300276 | 2023-09-27 23:31:35.315848 | USER         | FINISHED      |           2 |                   0 |        2 | OB_SUCCESS |
   | ttl_table  |   500002 |    200002 |       1 | 2023-09-27 23:31:30.300276 | 2023-09-27 23:31:35.320258 | USER         | FINISHED      |           1 |                   0 |        1 | OB_SUCCESS |
   | ttl_table  |   500002 |    200001 |       1 | 2023-09-27 23:31:30.300271 | 2023-09-27 23:31:35.321879 | USER         | FINISHED      |           0 |                   0 |        0 | OB_SUCCESS |
   | NULL       |       -1 |        -1 |       1 | 2023-09-27 23:31:28.675583 | 2023-09-27 23:31:28.675583 | USER         | RS_TRIGGERING |           0 |                   0 |        0 | OB_SUCCESS |
   +------------+----------+-----------+---------+----------------------------+----------------------------+--------------+---------------+-------------+---------------------+----------+------------+
   4 rows in set (0.043 sec)

   ```
 6. 任务执行完成会移动到历史表中，可以通过 `OCEANBASE.DBA_OB_KV_TTL_TASK_HISTORY` 表进行查看。

   ```shell
   obclient> SELECT * FROM OCEANBASE.DBA_OB_KV_TTL_TASK_HISTORY;

   ```

   返回结果如下：

   ```shell
   +------------+----------+-----------+---------+----------------------------+----------------------------+--------------+----------+-------------+---------------------+----------+------------+
   | 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   |
   +------------+----------+-----------+---------+----------------------------+----------------------------+--------------+----------+-------------+---------------------+----------+------------+
   | ttl_table  |   500002 |    200003 |       1 | 2023-09-27 23:31:30.300276 | 2023-09-27 23:31:35.315848 | USER         | FINISHED |           2 |                   0 |        2 | OB_SUCCESS |
   | ttl_table  |   500002 |    200002 |       1 | 2023-09-27 23:31:30.300276 | 2023-09-27 23:31:35.320258 | USER         | FINISHED |           1 |                   0 |        1 | OB_SUCCESS |
   | ttl_table  |   500002 |    200001 |       1 | 2023-09-27 23:31:30.300271 | 2023-09-27 23:31:35.321879 | USER         | FINISHED |           0 |                   0 |        0 | OB_SUCCESS |
   | NULL       |       -1 |        -1 |       1 | 2023-09-27 23:31:28.675583 | 2023-09-27 23:31:42.526853 | USER         | FINISHED |           0 |                   0 |        0 | OB_SUCCESS |
   +------------+----------+-----------+---------+----------------------------+----------------------------+--------------+----------+-------------+---------------------+----------+------------+
   4 rows in set (0.058 sec)

   ```
 7. 任务执行完成之后，可以看到所有过期数据已经被删除。

   ```shell
   obclient> SELECT * FROM ttl_table;
   Empty set (0.060 sec)

   ```

 上一篇 下一篇 ![有帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*y6ocSqN8cqsAAAAAAAAAAAAAARQnAQ)![无帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*BG9IQJyLHF8AAAAAAAAAAAAAARQnAQ)![反馈](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*eTWdQKCRKHwAAAAAAAAAAAAAARQnAQ)[AI](https://www.oceanbase.com/obi) 咨询热线
