首批通过分布式安全可靠测评,为关键业务系统打造
使用 TTL(Time To Live)功能
更新时间:2026-07-29 10:39:50
OceanBase 数据库 SQL 模式下的 TTL(Time To Live)功能提供了过期数据的管理能力。通过对表定义 TTL 策略来设置数据的有效期,再由系统执行过期数据(TTL)任务处理已过期的数据。
对于定义了 TTL 策略的表,系统对过期数据的处理主要分为以下两步:
当 TTL 任务被触发时,具有 TTL 属性的表及其索引表、辅助表会通过事务同步一个标记删除的规则信息,满足规则的数据行会被标记为删除,数据被标记删除后就会对用户不可见。
对于标记删除的数据,在下次执行 Compaction(合并)时,系统会将数据从存储层彻底删除,以便释放存储空间。
本文主要介绍如何通过命令或者设置周期性任务两种方式来发起过期数据(TTL)任务。
注意事项
对于 TTL 表,当 TTL 列的值为 NULL 时,该行数据永不过期;当新增列作为 TTL 列时,默认值为 NULL 的行的数据不会过期。
在 TTL 任务同步标记删除信息时,会对表加锁,与旁路导入、DDL、Transfer 等操作互斥。
当主表、索引表、辅助表等所有分区数超过 4000 时,可能会发生事务超时,导致标记删除信息的任务一直失败重试,可以通过调大超时时间解决,语句如下。
obclient(root@sys)[(none)]> ALTER SYSTEM SET internal_sql_execute_timeout = 600; /*sys 租户下执行,单位为秒*/由于标记删除信息的事务与普通 DML 事务不互斥,当两个事务并发且事务隔离级为 Read Committed,在 DML 事务内查询临近过期的数据时,可能会遇到幻读。
例如,假设有一个标记删除信息的事务
trans_A和一个普通 DML 事务trans_B,以及临近过期的数据行rowkey_A,在 T1 ~ T3(T1 < T2 < T3)这段时间内:- 在 T1 时间点:数据行
rowkey_A未达到过期时间,普通 DML 事务trans_B可以读取到rowkey_A的数据。 - 在 T2 时间点:数据行
rowkey_A达到过期时间,标记删除信息的事务trans_A将rowkey_A标记为删除。 - 在 T3 时间点:普通 DML 事务
trans_B再次读取rowkey_A,发现已读取不到该数据。
- 在 T1 时间点:数据行
当 TTL 任务未执行时,用户可以查询到表中符合过期规则的数据,若用户对过期数据有严格的可见性要求,需要在查询 SQL 中添加过滤条件。
在主表及其索引上执行 Offline DDL、新建索引的操作后,表数据会被重写,数据的写入时间会被更新,使得数据过期延迟。
执行 TTL 任务后,过期数据会在 Compaction(合并)过程中异步删除,删除过期数据的过程仅在 OceanBase 数据库内部进行,不会同步给下游的其他应用系统。
为了避免因并发写入而导致的数据丢失,对于使用用户定义的时间列作为 TTL 列的表,TTL 任务仅清理在任务开始前已过期数据,不会清理任务开始后过期的数据。
TTL 表的定义
使用限制
使用 TTL 功能进行过期数据的管理时,对 TTL 表有以下限制:
不支持外键约束。
不支持触发器。
不支持向量索引、全文索引。
仅支持 TTL 列为单列,不支持 TTL 列为虚拟列、生成列、表达式。
除了支持内部隐藏列
ora_rowscn(记录最后一次更新的时间戳),当前版本还支持用户定义的时间列作为 TTL 列。对于表更新模式为
partial_update的表,仅支持主键列或内部隐藏列ora_rowscn作为 TTL 列,且不支持表上带索引。对于 TTL 列为内部隐藏列
ora_rowscn的表,不允许为该表再添加列名为ora_rowscn的列。对于索引表,要求索引必须包含 TTL 列(原有列或 Storing 列形式)。如果现有索引不包含 TTL 列,需要先新建包含 Storing 列的索引后,再删除旧索引。
对于有 LOB 列的表:
- 允许创建表时使用用户列定义 TTL 属性,且表创建成功后,不允许修改 TTL 列为其他用户列。
- 不允许为没有 TTL 属性的表新增用户列的 TTL 属性。
- 允许将 TTL 列从用户定义的时间列切换为内部隐藏列
ora_rowscn。 - 允许删除 TTL 属性。
DDL 操作限制:
- 新增 TTL 属性时,要求所有索引表都包含 TTL 列。
- 变更 TTL 列时,要求所有索引表都包含新的 TTL 列。
- 删除 TTL 列时,需要先删除 TTL 属性。
创建具有 TTL 属性的表
创建 TTL 表的语句如下:
CREATE TABLE table_name (table_definition_list) MERGE_ENGINE = {append_only | delete_insert | partial_update}
TTL [=] col_name + INTERVAL interval_num ttl_unit BY COMPACTION;
语句中相关参数说明如下:
MERGE_ENGINE:指定表的更新模式。当前版本支持表更新模式MERGE_ENGINE为delete_insert、append-only或partial_update。col_name:指定 TTL 过滤列。支持指定内部隐藏列ora_rowscn(记录最后一次更新的时间戳)或用户定义的时间列。当 TTL 列为用户定义的时间列时,支持的列类型如下:
MySQL 模式:DATETIME、TIMESTAMP、DATE
Oracle 模式:DATE、TIMESTAMP、TIMESTAMP WITH TIME ZONE、TIMESTAMP WITH LOCAL TIME ZONE
interval_num:指定过期时间的整数数值,取值范围 [0,+∞)。值为0时,时间单位ttl_unit可以为取值中的任意值,表示数据一旦提交即过期。ttl_unit:指定过期时间的单位。取值支持SECOND、MINUTE、HOUR、DAY、MONTH或YEAR。
示例如下。
示例 1:创建一个数据过期时间为 7 天的 TTL 表。其中,TTL 列为内部隐藏列
ora_rowscn。MySQL 或 Oracle 模式下,执行以下语句创建 TTL 表。
obclient> CREATE TABLE ttl_tbl1( id INT PRIMARY KEY, val VARCHAR(100)) MERGE_ENGINE = append_only TTL ora_rowscn + INTERVAL 7 DAY BY COMPACTION;示例 2:创建一个数据过期时间为 7 天的 TTL 表。其中,TTL 列为用户定义的时间列。
MySQL 模式
obclient(root@mysql001)[infotest]> CREATE TABLE ttl_tbl2( order_id INT PRIMARY KEY, order_time DATETIME NOT NULL, payment_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP) MERGE_ENGINE = delete_insert TTL order_time + INTERVAL 7 DAY BY COMPACTION;oracle 模式
obclient(SYS@oracle001)[SYS]> CREATE TABLE TTL_TBL2( ORDER_ID INT PRIMARY KEY, ORDER_TIME DATE NOT NULL, PAYMENT_TIME DATE NOT NULL DEFAULT sysdate) MERGE_ENGINE = delete_insert TTL ORDER_TIME + INTERVAL 7 DAY BY COMPACTION;
修改表的 TTL 属性
表创建成功后,对于非 TTL 表,可以为表新增 TTL 属性;对于 TTL 表,可以修改 TTL 策略、变更 TTL 列或删除 TTL 属性。
新增 TTL 属性
为已有表新增 TTL 属性的语法如下:
ALTER TABLE table_name TTL [=] col_name + INTERVAL interval_num ttl_unit BY COMPACTION;
其中,col_name 用于指定 TTL 列,可以指定内部隐藏列 ora_rowscn 或用户定义的时间列。
以 MySQL 模式为例,假设当前存在一个非 TTL 表 tbl3。建表语句如下:
obclient(root@mysql001)[infotest]> CREATE TABLE tbl3(
order_id INT,
order_time DATETIME NOT NULL,
payment_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(order_id, order_time));
可以为表 tbl3 新增 TTL 属性,TTL 列为用户定义的时间列,示例语句如下:
obclient(root@mysql001)[infotest]> ALTER TABLE tbl3 TTL order_time + INTERVAL 7 DAY BY COMPACTION;
或者,也可以通过指定内部隐藏列 ora_rowscn 作为 TTL 列来为该表添加 TTL 属性。
obclient(root@mysql001)[infotest]> ALTER TABLE tbl3 TTL ora_rowscn + INTERVAL 7 DAY BY COMPACTION;
需要注意的是,本示例中,由于建表时未显式指定表的更新模型,系统默认为 partial_update 模式,而对于表更新模式为 partial_update 的表,在添加 TTL 属性时,TTL 列必须是主键列或内部隐藏列 ora_rowscn。
以 Oracle 模式为例,假设当前存在一个非 TTL 表 TBL3。建表语句如下:
obclient(SYS@oracle001)[SYS]> CREATE TABLE TBL3(
ORDER_ID INT,
ORDER_TIME DATE NOT NULL,
PAYMENT_TIME DATE NOT NULL DEFAULT sysdate,
PRIMARY KEY(ORDER_ID, ORDER_TIME));
可以为表 TBL3 新增 TTL 属性,示例语句如下:
obclient(SYS@oracle001)[SYS]> ALTER TABLE TBL3 TTL ORDER_TIME + INTERVAL 7 DAY BY COMPACTION;
或者,也可以通过指定内部隐藏列 ora_rowscn 作为 TTL 列来为该表添加 TTL 属性。
obclient(SYS@oracle001)[SYS]> ALTER TABLE TBL3 TTL ora_rowscn + INTERVAL 7 DAY BY COMPACTION;
需要注意的是,本示例中,由于建表时未显式指定表的更新模型,系统默认为 partial_update 模式,而对于表更新模式为 partial_update 的表,在添加 TTL 属性时,TTL 列必须是主键列或内部隐藏列 ora_rowscn。
修改 TTL 策略
TTL 表创建成功后,可以根据业务实际情况,修改表的 TTL 策略,示例语句如下:
obclient> ALTER TABLE ttl_tbl1 SET TTL ora_rowscn + INTERVAL 1 HOUR BY COMPACTION;
变更 TTL 列
变更 TTL 列的语法如下:
ALTER TABLE table_name TTL [=] new_ttl_col + INTERVAL interval_num ttl_unit BY COMPACTION;
其中,new_ttl_col 用于指定新的 TTL 列,与创建 TTL 表时的要求一致。如果是索引表,要求索引必须包含新的 TTL 列。
以 MySQL 模式为例,假设当前存在一个 TTL 表 ttl_tbl4。建表语句如下:
obclient(root@mysql001)[infotest]> CREATE TABLE ttl_tbl4(
order_id INT,
order_time DATETIME NOT NULL,
payment_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(order_id, order_time, payment_time))
MERGE_ENGINE = delete_insert TTL order_time + INTERVAL 7 DAY BY COMPACTION;
将表 ttl_tbl4 的 TTL 列从 order_time 变更为 payment_time,示例语句如下。
obclient(root@mysql001)[infotest]> ALTER TABLE ttl_tbl4 TTL payment_time + INTERVAL 7 DAY BY COMPACTION;
以 Oracle 模式为例,假设当前存在一个 TTL 表 TTL_TBL4,建表语句如下:
obclient(SYS@oracle001)[SYS]> CREATE TABLE TTL_TBL4(
ORDER_ID INT,
ORDER_TIME DATE NOT NULL,
PAYMENT_TIME DATE NOT NULL DEFAULT sysdate,
PRIMARY KEY(ORDER_ID, ORDER_TIME, PAYMENT_TIME))
MERGE_ENGINE = delete_insert TTL ORDER_TIME + INTERVAL 7 DAY BY COMPACTION;
将表 TTL_TBL4 的 TTL 列从 ORDER_TIME 变更为 PAYMENT_TIME,示例语句如下。
obclient(SYS@oracle001)[SYS]> ALTER TABLE TTL_TBL4 TTL PAYMENT_TIME + INTERVAL 7 DAY BY COMPACTION;
删除 TTL 属性
对于 TTL 表,如果不再需要使用 TTL 功能,可以删除表的 TTL 属性,示例语句如下。
obclient> ALTER TABLE ttl_tbl1 REMOVE TTL;
TTL 任务的触发
对于每一张定义了 TTL 属性的表,在开启 TTL 功能的情况下,系统内部会定期调度 TTL 任务来处理已过期的数据。执行 TTL 任务后,超过有效期的数据将会不可见,但是数据实际并未删除,过期数据会在 Compaction(合并)过程中异步删除(不占用 clog 和写入带宽)。待 Compaction(合并)任务执行后,过期数据占用的存储空间才会真正释放。
开启 TTL 功能
发起 TTL 任务要求当前租户已开启 TTL 功能。TTL 功能的开关由租户级配置项 enable_ttl(值为 True)控制,该配置项在新建租户、恢复租户的场景下其默认值均为 False,需要用户手动开启。
管理员用户登录到集群的
sys租户或用户租户。连接示例如下,连接数据库时请以实际环境为准。
obclient -h10.xx.xx.xx -P2883 -uroot@mysqltenant#obdemo -p***** -A执行以下语句,开启 TTL 功能。
系统租户为指定租户开启 TTL 功能。
obclient(root@sys)[(none)]> ALTER SYSTEM SET enable_ttl = True TENANT = tenant_name;用户租户为本租户开启 TTL 功能。
obclient> ALTER SYSTEM SET enable_ttl = True;
配置定时触发 TTL 任务的时间
开启 TTL 功能后,系统会根据租户下 TTL 表的数据过期情况,定时触发 TTL 任务。定时触发 TTL 任务的时间通过租户级配置项 ttl_duty_time 控制,默认触发时间为每天的凌晨 01:00。
ttl_duty_time 的时刻点与租户的时区相同,建议设置在租户的业务低峰期、租户每日合并发起之前。例如,修改为凌晨 02:00。
修改定时触发时间的操作如下:
管理员用户登录到集群的
sys租户或用户租户。连接示例如下,连接数据库时请以实际环境为准。
obclient -h10.xx.xx.xx -P2883 -uroot@mysqltenant#obdemo -p***** -A执行以下语句,修改 TTL 任务的定时触发 TTL 任务的时间。
系统租户为指定租户修改定时触发 TTL 任务的时间。
obclient(root@sys)[(none)]> ALTER SYSTEM SET ttl_duty_time = '02:00' TENANT = tenant_name;用户租户为本租户修改定时触发 TTL 任务的时间。
obclient> ALTER SYSTEM SET ttl_duty_time = '02:00';
手动触发 TTL 任务
开启 TTL 功能后,用户可以手动触发一次 TTL 任务。
管理员用户登录到集群的
sys租户或用户租户。连接示例如下,连接数据库时请以实际环境为准。
obclient -h10.xx.xx.xx -P2883 -uroot@sys#obdemo -p***** -A执行以下命令,手动触发一次 TTL 任务。
系统租户为所有用户租户手动触发一次 TTL 任务。
obclient(root@sys)[(none)]> ALTER SYSTEM TRIGGER TTL TENANT = all_user;注意
不支持系统租户通过
ALTER SYSTEM TRIGGER TTL TENANT = all_meta;语句为所有 Meta 租户手动触发 TTL 任务。系统租户为指定租户手动触发一次 TTL 任务。
obclient> ALTER SYSTEM TRIGGER TTL TENANT = tenant_name;用户租户为本租户手动触发一次 TTL 任务。
obclient> ALTER SYSTEM TRIGGER TTL;
TTL 任务的状态
TTL 任务执行过程中,可以通过视图 CDB_OB_TTL_TASKS(sys 租户)或 DBA_OB_TTL_TASKS(用户租户)来查看正在执行过程中的 TTL 任务详情,包含表信息、开始时间、修改时间、执行状态等。
系统租户
obclient(root@sys)[(none)]> SELECT * FROM oceanbase.CDB_OB_TTL_TASKS;用户租户
obclient(root@mysqltenant)[(none)]> SELECT * FROM oceanbase.DBA_OB_TTL_TASKS; /*MySQL 模式*/obclient(root@oracletenant)[SYS]> SELECT * FROM SYS.DBA_OB_TTL_TASKS; /*Oracle 模式*/
用户租户下查询结果的示例如下:
+------------+----------+---------+----------------------------+----------------------------+--------------+------------+------------+------------+
| TABLE_NAME | TABLE_ID | TASK_ID | START_TIME | MODIFIED_TIME | TRIGGER_TYPE | STATUS | RET_CODE | TASK_TYPE |
+------------+----------+---------+----------------------------+----------------------------+--------------+------------+------------+------------+
| NULL | -1 | 1 | 2026-01-28 17:31:27.624387 | 2026-01-28 17:31:27.624387 | USER | TRIGGERING | OB_SUCCESS | COMPACTION |
+------------+----------+---------+----------------------------+----------------------------+--------------+------------+------------+------------+
1 row in set
查询结果中,相关字段的详细说明,参见 CDB_OB_TTL_TASKS 和 DBA_OB_TTL_TASKS。
TTL 任务执行结束后,还可以通过视图 CDB_OB_TTL_TASK_HISTORY(sys 租户) 或 DBA_OB_TTL_TASK_HISTORY(用户租户) 来查看已完成的 TTL 任务历史。
注意
TTL 任务历史信息的数据保留时间受租户级配置项 kv_ttl_history_recycle_interval 控制,默认保留 7 天。
TTL 任务的管控
TTL 任务执行过程中,支持手动暂停、恢复或取消 TTL 任务。
暂停 TTL 任务
手动或定时触发 TTL 任务后,可以根据业务需要,手动暂停正在执行的 TTL 任务。
系统租户暂停所有用户租户的 TTL 任务。
obclient(root@sys)[(none)]> ALTER SYSTEM SUSPEND TTL TENANT = all_user;系统租户暂停指定租户的 TTL 任务。
obclient(root@sys)[(none)]> ALTER SYSTEM SUSPEND TTL TENANT = tenant_name;用户租户暂停本租户的 TTL 任务。
obclient> ALTER SYSTEM SUSPEND TTL;
恢复已暂停的 TTL 任务
TTL 任务被暂停后,可以手动恢复已暂停的 TTL 任务。
系统租户恢复所有用户租户的 TTL 任务。
obclient(root@sys)[(none)]> ALTER SYSTEM RESUME TTL TENANT = all_user;系统租户恢复指定租户的 TTL 任务。
obclient(root@sys)[(none)]> ALTER SYSTEM RESUME TTL TENANT = tenant_name;用户租户恢复本租户的 TTL 任务。
obclient> ALTER SYSTEM RESUME TTL;
取消 TTL 任务
TTL 任务执行过程中,用户可以根据业务需要,手动取消正在执行的 TTL 任务。
系统租户取消所有用户租户的 TTL 任务。
obclient(root@sys)[(none)]> ALTER SYSTEM CANCEL TTL TENANT = all_user;系统租户取消指定租户的 TTL 任务。
obclient(root@sys)[(none)]> ALTER SYSTEM CANCEL TTL TENANT = tenant_name;用户租户取消本租户的 TTL 任务。
obclient> ALTER SYSTEM CANCEL TTL;