四海内皆兄弟

TDSQL Boundless V21.6.4 数据生命周期与降本实战


 表级 TTL 自动过期 · TTL 归档到指定表 · 自动日期分区,真机实测与踩坑

一、数据生命周期与降本:数据留得久,成本降得下

继续上次COS特性后,官方升级到了V21.6.4,推出了一些新功能。为了体验这些功能,利用腾讯云的资源开通了TDSQL-B(即TDSQL Boundless)的验证环境。

做数据库运维的可能都经历过订单、日志、审计、埋点这些表,而这些中除了订单数据,其他都是低价值数据,留着占高性能存储,仅仅是偶尔用来查个日志。传统做法是 DBA 人工处理。

TDSQL-B在 V21.6.4 把“数据价值随时间衰减”这件事,直接交给数据库内核去自动完成——分区自动创建、过期自动清理、冷数据自动落对象存储。全程对应用透明:SQL 不改、连接不变、外部调度脚本一套都不用写。这一块是本次发布投入最大、也最容易见效的部分,本实战就聚焦这里。

二、实验环境

项目

说明

实例内核

8.0.26.0.0-sqlengine-21.6.4.1(TDSQL Boundless)

实例标识

hybrid-0(server_id=64120;SQL 节点 node-tdsql3-kxbig6pevo-001/002)

存储引擎

ROCKSDB(LSM-Tree)

连接方式

跳板机 139.199.180.243 → mysql -udbaadmin -h 10.10.0.94

对照实例

106.55.69.143(21.6.3.0,三项新特性均不可用)

测试库

ttl_test

三、能力 A:表级 TTL 自动过期

3.1 它要解决什么

10多年前我第一次看到TTL这个概念是在Redis和CDH这些产品上。在关系型数据库为主的数据库上不多见。

日志、会话、审计、埋点类表,数据偶尔被查询一下。太久远的数据就没有用了。这种特别适合TTL这种场景。现在只需在建表时声明一行 TTL 表达式,数据库后台分批自动清理,进度可查可审计。

3.2 正确语法(真机验证)

CREATE TABLE app_log (

id BIGINT NOT NULL,

created_at DATETIME NOT NULL,

content VARCHAR(200),

PRIMARY KEY (id)

) TTL = created_at + INTERVAL 90 DAY, -- 表达式【不加引号】

TTL_ENABLE = 'ON',

TTL_JOB_INTERVAL = '1m'; -- 扫描间隔值需引号

-- 查看 TTL 元数据

SELECT SCHEMA_NAME, TABLE_NAME, TTL_ENABLE, TTL_COLUMN,

TTL_DURATION, TTL_INTERVAL_TYPE, TTL_JOB_INTERVAL,

ARCHIVE_TABLE, ARCHIVE_ON_CONFLICT

FROM information_schema.TTL_TABLES

WHERE SCHEMA_NAME='ttl_test'\G

关键坑 1:TTL 表达式的值不能加引号。最初写成 TTL = 'created_at + INTERVAL 90 DAY'(照搬官方示例的引号),建表直接报 1064。正确写法是 TTL = created_at + INTERVAL 90 DAY,只有 TTL_ENABLE / TTL_JOB_INTERVAL 这类参数值才需要引号。

3.3 TTL 列类型边界(真机实测)

官方文档说 TTL 列须为日期时间类型,我们专门做了边界验证:

列类型

建表结果

说明

DATETIME

✅ 成功

主推类型

DATE

✅ 成功

同族,支持

TIMESTAMP

✅ 成功

同族,支持

VARCHAR

❌ ERROR 8643

TTL column must be of type DATE, DATETIME, or TIMESTAMP

BIGINT

❌ ERROR 8643

整数时间戳不支持,需先转日期类型

关键坑 2:很多开发人员为了应用程序处理方便会把时间存成 VARCHAR 或 BIGINT(如 20260920、1738368000)。这两类在 TTL 场景会被直接拒绝,报错 8643。要么改用 DATETIME 列,要么在写入前转换。别指望 TTL 帮你隐式转换——它既不转、也不会静默出错。

3.4 元数据视图与真实约束

TTL 状态可从 information_schema.TTL_TABLES 查询,但列名与直觉略有差异(是 SCHEMA_NAME 而非 TABLE_SCHEMA,是 ARCHIVE_TABLE 而非 TTL_ARCHIVE_TABLE),查询时别写错列名。

*************************** 1. row ***************************

SCHEMA_NAME: ttl_test

TABLE_NAME: app_log

TTL_ENABLE: ON

TTL_COLUMN: created_at

TTL_DURATION: 90

TTL_INTERVAL_TYPE: DAY

TTL_JOB_INTERVAL: 1m

ARCHIVE_TABLE: ttl_test.app_log_archive

ARCHIVE_ON_CONFLICT: STOP

关键坑 3(踩坑实录):TTL 的后台清理/归档依赖全局开关 ttl_enable=ON,默认是关的。我这边 dbaadmin 没有 SUPER 权限,SET GLOBAL 开不了(报 ERROR 1227),所以一开始只能验到建表、语法、视图和类型报错这一层。后来找官方帮忙在后台把 ttl_enable 打开,顺手把调度窗口从默认的 00:00~06:00 调成了 00:00~23:59。再查已经确认:ttl_enable=ON,sys.ttl_task_history 里 app_log 的归档任务也真的跑出了 finished 记录——后台动作这次是真验到了。生产上记得确认开关已开,窗口按业务高峰再定。

四、能力 B:TTL 归档到指定表

“过期就删”有时候太粗暴——审计、合规场景要求数据不能真没,只是从主表挪走。TTL 归档到指定表就是干这个:到期数据先写入归档表、再从原表删除,事务一致,归档表本身还能再落冷。

4.1 语法与约束(真机验证)

-- 声明归档目标表

ALTER TABLE orders SET TTL_ARCHIVE_TABLE = 'orders_archive';

-- 归档表需满足:显式主键、列是源表超集

CREATE TABLE orders_archive (

id BIGINT NOT NULL, created_at DATETIME NOT NULL,

content VARCHAR(200), PRIMARY KEY (id)

);

-- 冲突策略:STOP(默认,遇主键冲突停) / REPLACE(覆盖)

-- TTL_ARCHIVE_ON_CONFLICT

归档表必须含显式主键,且列集合要覆盖原表(否则归档写入会失败)。

CREATE TABLE ... LIKE 复制表结构时,TTL 定义【不会】跟随——我们实测 dst 表是干净的、不带 TTL。需要归档能力得显式再声明。

官方把 ttl_enable 打开后,归档这次是真的跑起来了:app_log_archive 已落入 2 行(2026-05-23、2026-06-12,都超过 90 天),原表 app_log 同步清理到只剩 2 行窗口内数据,sys.ttl_task_history 里任务 strategy=archive_then_delete、status=finished。开启前那段手动模拟只作语义对齐,真实生产由后台任务执行。

实践建议:归档表和原表建议放在同一 schema;归档表可进一步用上一版冷热分离能力(STORAGE_TIER=OBJECT_STORAGE)落对象存储,做到“主表热、归档冷”的二级降本。

五、能力 C:自动日期分区(INTERVAL RANGE)

时间序列表(订单、流水、日志)按月/天分区是常识,但传统 RANGE 分区有个老大难:未来分区得人工提前建,建少了写入报“找不到分区”,建多了又浪费。Oracle数据库有这个功能,相比起而言MySQL至今没有这个功能。所有运维起来我经常看到MySQL的同事每到一定月份就要手工增加。而Oracle的运维没有这些事务。而如今V21.6.4 也具备了这样的功能, INTERVAL RANGE 让数据库按指定间隔自动补齐未来分区。

5.1 正确语法(官方文档 + 真机实测)

语法要点:INTERVAL 子句紧跟在分区定义之后。日期时间列(DATETIME/DATE/TIMESTAMP)走 RANGE COLUMNS 形式——PARTITION BY RANGE COLUMNS(col) INTERVAL(MONTH, N);整数列(INT/BIGINT)走 RANGE 形式——PARTITION BY RANGE(col) INTERVAL(N)。interval_type 支持 YEAR、QUARTER、MONTH、WEEK、DAY、HOUR、MINUTE、SECOND 共 8 种,N 必须是正整数常量。

-- 日期时间列:RANGE COLUMNS + INTERVAL(MONTH, N)

CREATE TABLE m_log (id BIGINT NOT NULL, ts DATETIME NOT NULL,

content VARCHAR(100), PRIMARY KEY (id, ts))

PARTITION BY RANGE COLUMNS (ts) INTERVAL (MONTH, 1) (

PARTITION p202601 VALUES LESS THAN ('2026-02-01'));

-- 整数列:RANGE + INTERVAL(N)

CREATE TABLE m_int (id BIGINT NOT NULL, v BIGINT NOT NULL,

content VARCHAR(100), PRIMARY KEY (id, v))

PARTITION BY RANGE (v) INTERVAL (100)

(PARTITION p0 VALUES LESS THAN (100));

-- 两种写法均在本实例实测通过,自动建分区结果见下表。

5.2 自动建分区——真机验证

建表时只声明 1 个起始分区 p202601,然后插入三行一路跨到 2027 年 03 月的数据,看系统会不会自动补齐月份分区:

INSERT INTO m_log VALUES

(1,'2026-01-15 10:00:00','in p202601'),

(2,'2026-09-20 10:00:00','spill -> auto month'),

(3,'2027-03-01 10:00:00','far future -> auto month');

SELECT PARTITION_NAME, PARTITION_DESCRIPTION, TABLE_ROWS

FROM information_schema.PARTITIONS

WHERE TABLE_SCHEMA='ttl_test' AND TABLE_NAME='m_log'

插入后分区视图(节选):系统按月自动补齐了分区,数据正确落入对应月份:

分区名

上界(VALUES LESS THAN)

行数

p202601

'2026-02-01'

1 ← 2026-01-15

_p20261001000000

'2026-10-01'

1 ← 2026-09-20

…(每月一个,系统自动补齐)

…

…

_p20270401000000

'2027-04-01'

1 ← 2027-03-01

实测结论:建表只用 RANGE COLUMNS (ts) INTERVAL (MONTH, 1) 加 1 个起始分区 p202601,插入 2026-01、2026-09、2027-03 三行跨越 14 个月的数据后,系统自动补齐了按月分区——共 15 个(1 个起始 p202601 + 14 个自动创建的 _p202603…_p202704),数据正确落入对应月份。整数列用 INTERVAL(100) 同样自动建出 _p200、_p300、_p400,两种写法都验证通过。整个过程不需要任何外部调度脚本。

六、真机实测:TTL 建表 + 边界 + 归档路径

下面把本次连环境跑通的完整过程贴出,便于复现。所有 SQL 通过跳板机文件重定向方式执行(多行 SQL 不能用 -e 直传,MariaDB 客户端会破坏分号)。

6.1 建表声明层(成功)

CREATE TABLE app_log (

id BIGINT NOT NULL, created_at DATETIME NOT NULL, content VARCHAR(200),

PRIMARY KEY (id)

) TTL = created_at + INTERVAL 90 DAY, TTL_ENABLE='ON', TTL_JOB_INTERVAL='1m';

-- Query OK, 0 rows affected ✅

SHOW CREATE TABLE app_log; -- 确认 TTL 已生效

6.2 边界类型验证

CREATE TABLE t_int (id BIGINT, d BIGINT, PRIMARY KEY(id))

TTL = d + INTERVAL 90 DAY;

-- ERROR 8643 (HY000): TTL column 'd' must be of type

-- DATE, DATETIME, or TIMESTAMP ❌ 整数时间戳被拒

CREATE TABLE t_date (id BIGINT, d DATE, PRIMARY KEY(id))

TTL = d + INTERVAL 90 DAY;

-- Query OK ✅ DATE 同族支持

6.3 归档路径与后台任务(官方开启 ttl_enable 后)

-- 查看后台 TTL 任务执行情况

SELECT task_id, table_name, strategy, status, deleted_rows, finished_at

FROM sys.ttl_task_history

WHERE table_schema='ttl_test' AND table_name='app_log'

ORDER BY task_id DESC LIMIT 3;

-- 归档结果核对:

SELECT COUNT(*) FROM app_log; -- 2 行(90 天窗口内保留)

SELECT COUNT(*) FROM app_log_archive; -- 2 行(超过 90 天,自动迁入)

七、增强项:对象存储(COS)自动落冷二期

在上一版“冷热分离”基础上,V21.6.4 把能力从“表级手动”细化到“分区级自动”:基于日期分区自动识别冷数据并下发转冷任务,冷数据仍属于原表、仍可用标准 SQL 查询,并具备备份恢复与点查加速。这一项是增强而非全新,但和前面的 TTL / 自动分区天然搭配——自动分区管“切”,自动落冷管“沉”。

-- ① 创建落冷规则:分区键 yyyymm → 时间,超 6 个月落冷

CREATE DISTRIBUTION POLICY "auto_cooldown_6m" SET

PARTITION_METHOD = "RANGE" AND

PARTITION_KEY_TO_TIME_TYPE = (

"sql:STR_TO_DATE(CONCAT(BOUND,'01'),'%Y%m%d')") AND

EXPIRE = "6 MONTH" AND

STORAGE_TIER = "OBJECT_STORAGE";

-- ② 建分区表并导入数据(官方推荐:先导数,再绑定规则)

CREATE TABLE orders (

id BIGINT NOT NULL, yyyymm INT NOT NULL, data VARCHAR(255),

PRIMARY KEY (id, yyyymm)

) PARTITION BY RANGE (yyyymm) (...);

-- ③ 绑定规则,触发分区级自动落冷

ALTER TABLE orders USING DISTRIBUTION POLICY "auto_cooldown_6m";

八、总结与上线建议

8.1 三项能力一句话定位

能力

解决的真问题

真机验证结论

A 表级 TTL 自动过期

日志/会话/审计类表到期自动清理,免手写调度

✅ 已真验:官方开启 ttl_enable 后,后台 archive_then_delete 任务跑通,app_log_archive 落 2 行、原表同步清理

B TTL 归档到指定表

过期数据保留合规,先归档再删、事务一致

✅ 已真验:官方开后归档后台执行,过期行迁入归档表、原表清理

C 自动日期分区

时间序列表未来分区自动补齐,杜绝写入失败

✅ 已真验:官方语法 INTERVAL(MONTH, 1) 自动按月建分区,数据正确落位

Image