TDengine 数据删除(DELETE)实战指南:语法、安全删除与磁盘空间回收
【免费下载链接】tdengineTDengine is an open source, high-performance, cloud native time-series database optimized for Internet of Things (IoT), Connected Cars, Industrial IoT and DevOps.项目地址: https://gitcode.com/taosdata/tdengine
TDengine 的DELETE语句用于从普通表、子表或超级表中删除数据,是清理设备故障等产生的异常数据的主要手段。本文围绕DELETE的完整语法、参数约束、底层实现原理展开,并结合SECURE_DELETE安全删除、KEEP过期回收与COMPACT数据重组等机制,帮助你在生产环境中安全、正确地删除时序数据并理解磁盘空间何时才能真正释放。
DELETE 语句语法
DELETE语句从指定的表或超级表中删除数据,适用于清理设备故障等原因产生的异常数据。完整语法如下:
DELETE FROM [db_name.]tb_name [WHERE condition] [SECURE_DELETE];核心注意点:删除数据并不会立即释放磁盘空间。被删除的行只是被标记为已删除,查询时不再返回,但磁盘空间要等到数据库的KEEP设置生效(过期数据自动回收),或手动执行 数据重组(企业版COMPACT) 时才会真正回收。如果希望在写入删除标记之外,同时物理覆写磁盘上的数据块,需要使用数据库级或语句级的SECURE_DELETE,详见 数据安全 · 安全删除。
参数说明
| 参数 | 必填 | 说明 |
|---|---|---|
db_name | 否 | 表所在的数据库名,省略时使用当前数据库。 |
tb_name | 是 | 要删除数据的表,可以是普通表、子表或超级表。 |
condition | 否 | 可选过滤条件。不带过滤条件时删除表中全部数据,请谨慎使用。WHERE只支持对第一列(主键时间戳列)进行过滤。 |
SECURE_DELETE | 否 | 可选关键字。指定后,本次删除还会对匹配时间范围内的磁盘数据块进行物理覆写。也可以通过CREATE DATABASE ... SECURE_DELETE 1为数据库默认开启安全删除(见 Databases)。 |
重要提示
数据一旦删除无法恢复,请谨慎操作。在确认要删除的行之前,建议先使用相同的WHERE条件执行一次SELECT预览结果,确认无误后再执行DELETE。
完整示例
假设meters是一个超级表,groupId是其INT类型的标签列。下面的语句删除meters中所有时间戳早于2021-10-01 10:40:00.100的数据:
DELETE FROM meters WHERE ts < '2021-10-01 10:40:00.100';执行后,结果以如下形式展示:
Deleted 102000 row(s) from 1020 table(s) (0.421950s)这表示从 1020 个子表中总共删除了 102000 行数据。
无 WHERE 条件的全表删除
如果不带WHERE条件,语句会删除目标表(或超级表下所有子表)的全部数据:
DELETE FROM meters;这类操作影响面大且不可恢复,执行前务必确认目标。超级表场景下,删除会作用于该超级表的全部子表。
删除前的安全确认流程
由于删除不可恢复,推荐的确认流程如下:
先用相同的过滤条件查询,确认影响范围:
SELECT count(*) FROM meters WHERE ts < '2021-10-01 10:40:00.100';确认行数符合预期后,再执行
DELETE。
WHERE 条件的过滤限制
DELETE的WHERE子句只支持对**第一列(主键时间戳列)**进行过滤,不能像普通查询那样组合多个列的任意条件。这是由 TDengine 的存储与删除机制决定的:删除以时间范围为粒度在存储引擎中定位数据块,因此过滤条件被限定为时间戳范围。
常见用法示例:
-- 删除指定时间范围内的数据 DELETE FROM d1001 WHERE ts >= '2021-10-01 00:00:00' AND ts < '2021-10-02 00:00:00'; -- 删除某个时间点之前的所有数据 DELETE FROM meters WHERE ts < '2021-10-01 10:40:00.100';删除的底层原理:删除标记(Delete Marker)
从源码结构看,TDengine 的删除并非即时物理抹除,而是采用「删除标记 + 延迟回收」的设计:
写入删除标记:删除请求到达 vnode 后,存储引擎在内存表中追加一条删除记录(
SDelData),记录版本号与起止时间戳sKey/eKey,同时将缓存中的对应数据失效。核心实现位于 tsdbMemTable.c 的tsdbDeleteTableData()。查询屏蔽:后续查询通过删除标记(如
tsdbKeyDeleted,见 tsdbCache.c)在访问数据块时过滤已删除的行,因此用户层面“看不到”被删除的数据。延迟回收:数据文件中的实际空间,要等到数据超过数据库
KEEP保留期被自动清理,或企业版手动执行COMPACT数据重组时,才会从文件中剔除并真正归还磁盘。
正是这个设计,使得DELETE在写入路径上开销较小,同时带来了「删除后磁盘空间不立即释放」的语义。
SECURE_DELETE:安全删除
默认情况下,删除只写删除标记,磁盘上对应数据块的内容仍然存在,存在被直接从文件系统层面恢复读取的风险。SECURE_DELETE在写入删除标记之外,还会对磁盘上 DATA / STT 文件中匹配(表, 时间范围)的数据块进行文件级物理覆写,降低删除内容被直接解读的风险。
三级开启方式与 OR 组合语义
SECURE_DELETE可以在三个层级开启,最终生效条件是三者按**位或(OR)**合并:
数据库级:建库或改库时开启,例如:
CREATE DATABASE db SECURE_DELETE 1; ALTER DATABASE db SECURE_DELETE 1;数据库参数
SECURE_DELETE的取值为0(默认)或1:0:删除仅写删除标记,不立即物理覆写磁盘数据块;1:除写删除标记外,同时物理覆写磁盘上 DATA/STT 文件中对应范围的数据块。
该参数可通过
CREATE DATABASE或ALTER DATABASE设置,具体 DDL 说明见 Databases · SECURE_DELETE。表/超级表级:建表或改表时开启,与数据库级、语句级进行 OR 合并:
CREATE STABLE meters ( ts TIMESTAMP, current FLOAT, voltage INT ) TAGS (location VARCHAR(64)) SECURE_DELETE 1; ALTER STABLE meters SECURE_DELETE 1;语句级:单条
DELETE语句后追加关键字:DELETE FROM meters WHERE ts < '2021-10-01 10:40:00.100' SECURE_DELETE;
源码中的 OR 合并链路
从源码可以清晰看到三级配置的合并过程:
语法层:
sql.y定义了cmd ::= DELETE FROM full_table_name where_clause_opt SECURE_DELETE.规则(见 sql.y);parAstCreater.c 中的createSecureDeleteStmt()在普通 DELETE 语句上设置secureDelete = 1。规划层:物理计划生成时,将语句级与表/超级表元数据中的
secureDelete合并,见 planLogicCreater.c:// merge: statement-level SECURE_DELETE keyword OR super table/db secureDelete metadata pModify->secureDelete = pDelete->secureDelete | pRealTable->pMeta->secureDelete;执行层:vnode 处理删除请求时,再与数据库级运行时配置合并,避免客户端元数据过期导致漏配,见 vnodeSvr.c:
// Merge runtime vnode(db-level) secureDelete to avoid stale client meta after ALTER DATABASE. int8_t secureDelete = pRes->secureDelete | pVnode->config.secureDelete; code = tsdbDeleteTableData(pVnode->pTsdb, ver, pRes->suid, uid, pRes->skey, pRes->ekey, secureDelete);存储层:
tsdbDeleteTableData()在写入删除标记之前,先调用tsdbSecureEraseFileRange()对磁盘数据文件与 STT 文件的目标范围做物理覆写;覆写失败仅记录日志而不会中断删除,因为删除标记本身已保证查询语义正确(已删除数据不会因覆写失败而重新可见),见 tsdbMemTable.c 与 tsdbSecureErase.c。
SECURE_DELETE 的行为细节与限制
- 多副本场景:文件级物理覆写只在 Raft Leader 上执行,Followers 通过 WAL 回放逻辑删除,不会重复执行同样的物理覆写。
- 文件格式限制:当前实现针对较新的 TSDB 文件格式;旧格式文件会跳过文件级覆写,依赖后续 compaction 路径回收。
- 残余可见性:WAL 在 checkpoint 后的 WAL trimming 之前仍可能保留原始写入记录;操作系统页缓存与 SSD 磨损均衡也可能让旧内容在物理介质上短暂可见。该功能不是硬件级 Secure Erase / Sanitize,也不等同于「静态加密 + 销毁密钥」。
- 性能开销:开启后删除路径的 I/O 与延迟会上升,需要在「残留数据清除需求」与「性能代价」之间权衡。
- 填充模式:全局参数
secureEraseMode(默认0)控制整块可覆写时的填充方式:0为零填充,1为随机字节;部分重叠的数据块为保持原地写回始终采用零填充。详见 taosd · secureEraseMode。 - 与 TDE 的关系:安全删除与静态加密(TDE)互补——TDE 降低直接解读静态文件的风险,安全删除聚焦于删除后残留数据块的物理覆写。
删除后磁盘空间的回收
删除标记只屏蔽可见性,真正释放空间依赖以下两种机制:
1. KEEP 过期自动回收
数据库参数KEEP表示数据文件保留的天数,默认值 3650,取值范围[1, 365000],且必须大于等于DURATION参数值的 3 倍。数据库会自动删除保存时间超过KEEP值的数据以释放存储空间,详见 Databases · KEEP。
KEEP支持带单位写法(如KEEP 100h、KEEP 10d,支持 m/h/d 三种单位),也可不带单位(默认天,如KEEP 50表示 50 天)。
2. COMPACT 数据重组(企业版)
TDengine Enterprise 提供数据重组功能(DATA COMPACT),用于重组存储数据文件、去除文件空洞与无效数据。删除操作产生的「已删除数据」和「已删除表的数据」都会在 COMPACT 时被真正清除。常用命令:
COMPACT DATABASE db_name [start with 'XXXX'] [end with 'YYYY'] [META_ONLY] [FORCE]; SHOW COMPACTS; SHOW COMPACT compact_id; KILL COMPACT compact_id;要点:
- COMPACT 为异步后台任务,执行后立即返回任务 ID;可通过
SHOW COMPACTS查看进度,用KILL COMPACT终止任务。 - 自上次重组以来没有新数据写入的文件组不会被重组,除非指定
FORCE。 - COMPACT 可能阻塞写入(尤其
stt_trigger = 1的数据库),但不阻塞查询。
完整的 COMPACT 语法与效果说明见 维护集群 · 数据重组。
使用建议与最佳实践
- 删除前先 SELECT 确认:以相同
WHERE条件先查询行数,再执行删除,避免误删。 - 明确时间范围:尽量给出精确的
ts范围,减少无谓的全表/大范围删除;超大范围删除会拉长删除路径耗时并产生大量删除标记。 - 按需开启 SECURE_DELETE:对敏感数据场景,优先在建库时统一开启
SECURE_DELETE 1,避免逐条语句追加关键字遗漏;同时评估删除路径的 I/O 与延迟开销。 - 理解空间回收节奏:删除后磁盘空间不会立即释放,可结合
KEEP过期回收或企业版COMPACT规划空间回收窗口。 - 注意副本与文件格式差异:多副本场景下物理覆写仅发生在 Leader;旧格式文件依赖后续 compaction 回收,必要时结合版本升级规划。
相关阅读
| 主题 | 文档 |
|---|---|
数据库 DDL(KEEP、SECURE_DELETE等参数) | Databases |
| 数据安全(静态加密与安全删除) | Data-at-Rest Protection |
| 集群维护与数据重组(COMPACT) | Maintaining Your Cluster |
taosd加密与擦除相关参数 | taosd |
【免费下载链接】tdengineTDengine is an open source, high-performance, cloud native time-series database optimized for Internet of Things (IoT), Connected Cars, Industrial IoT and DevOps.项目地址: https://gitcode.com/taosdata/tdengine
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考