5.写入路径 > 05 数据删除与更新 --- DELETE/UPDATE 语义与故障诊断

适用版本 :TDengine v3.x(v3.3.x / v3.4.x) | 最后更新:2026-06-26
概述
时序场景 写多读多、改少删少 。TDengine 支持 DELETE、UPDATE、DROP、TRUNCATE,但带有 必须含时间条件 等时序库特有约束。本文说明语义、内部机制(Tombstone / 同 ts 覆盖),以及 删改操作的专属报错与排查。
v3 起所有库 默认支持部分列更新 ;2.x 的 CREATE DATABASE ... UPDATE 0/1/2 选项已废除。
核心概念
| 概念 | 说明 |
|---|---|
| DELETE | 按时间范围逻辑删除,Compaction 后物理清理 |
| UPDATE | 按 ts 更新列;未指定列保留原值 |
| Tombstone | DELETE 产生的删除标记 |
| INSERT 同 ts | 写入路径上的 Upsert,见 01 篇 |
| KEEP | 自动过期删除,优于手工 DELETE |
| TRUNCATE | 清空库数据,保留 Schema |
详细解析
1. DELETE 语法与约束
sql
-- 子表:时间范围删除
DELETE FROM d1001 WHERE ts >= '2026-06-01' AND ts < '2026-06-02';
-- 超级表:带 Tag 过滤
DELETE FROM meters WHERE ts < '2026-01-01' AND location = 'Beijing';
硬约束:
| 规则 | 说明 |
|---|---|
| 必须有 ts 条件 | 无时间范围的 DELETE 被拒绝 |
| 不支持子查询 / JOIN | 简化实现、防全表扫误删 |
| 超级表 DELETE | 作用于匹配子表集合 |
错误示例:
DELETE FROM meters WHERE current > 100;
→ Invalid delete: 缺少明确时间窗口
正确示例:
DELETE FROM meters WHERE ts < '2026-01-01' AND current > 100;
2. DELETE 内部机制
DELETE 请求
│
▼
解析目标表 + 时间范围 [ts_start, ts_end]
│
▼
写 Tombstone 记录(WAL + MemTable)
标记 (table_id, ts_start, ts_end) 为已删除
│
▼
查询时:读数据块 + 过滤 Tombstone 范围
│
▼
后台 Compaction:物理移除数据,释放空间
用户体验:
- DELETE 成功后 立即查不到 范围内数据
- 磁盘空间不会立即下降;需等 Compaction
- 大量 DELETE → Tombstone 增多 → 查询过滤开销上升
3. UPDATE 语法
sql
UPDATE d1001 SET current = 28.5 WHERE ts = '2026-06-01 12:00:00';
UPDATE d1001 SET current = 28.5, voltage = 222
WHERE ts >= '2026-06-01' AND ts < '2026-06-02';
约束:
| 规则 | 说明 |
|---|---|
| 必须有 ts 精确或范围条件 | 同 DELETE |
| 不能改 ts 主键 | PRIMARY KEY 不可 UPDATE |
| 不能改 Tag | 用 ALTER TABLE ... SET TAG |
| 未指定列 | v3 保留原值(部分列更新) |
4. UPDATE vs INSERT 同 ts
| 方式 | 行为 | 适用 |
|---|---|---|
INSERT ... 同 ts |
部分列覆盖,其余保留 | 流式修正单点 |
UPDATE ... WHERE ts= |
显式 SET 列 | 语义清晰、批量改列 |
DELETE + INSERT |
完全替换行 | 大范围重做 |
两者最终都走 写入路径(WAL → MemTable),不是原地改磁盘文件。
5. DROP 与 TRUNCATE
sql
DROP TABLE d1001; -- 删子表
DROP STABLE meters; -- 删超级表及全部子表
DROP DATABASE test_db; -- 删库
| 操作 | Schema | 数据 | 可恢复 |
|---|---|---|---|
| DELETE | 保留 | 逻辑删 | 否(无 undo) |
| DROP TABLE | 删除 | 异步清理文件 | 否 |
6. 删改校验链
DELETE / UPDATE
│
▼
① 语法 + 表存在性(同 INSERT)
│
▼
② WHERE 必须含 ts 有效范围
└─ The DELETE statement must only have a definite time window range
│
▼
③ 权限 WRITE
│
▼
④ VNode:Tombstone 或新行写入
│
▼
⑤ 副作用:Last 缓存失效、Stream/RSMA 可能重算
7. 删改故障诊断表
| 错误消息 | 根因 | 处理 |
|---|---|---|
The DELETE statement must only have a definite time window range |
WHERE 无 ts 或范围不明确 | 加 ts >= ... AND ts < ... |
| UPDATE 无此报错但语义不对 | WHERE 过宽,误改多行 | 先用 SELECT 同条件预览 |
| DELETE 成功但空间不减 | Tombstone 未 Compaction | 等待或 COMPACT;长期用 KEEP 代替 |
| DELETE 后 Stream 结果异常 | 流任务未忽略删改 | 检查 Stream IGNORE UPDATE / DELETE_MARK |
Permission denied |
无 WRITE | GRANT |
Table does not exist |
表名错 | SHOW TABLES |
| UPDATE 报 ts 相关错 | WHERE 未命中任何行 | 非错误;affected_rows=0 |
8. 推荐实践:KEEP 代替手工 DELETE
sql
CREATE DATABASE power KEEP 365; -- 超 365 天自动清理
ALTER DATABASE power KEEP 90; -- 缩保留期
KEEP 在文件级删除,无 Tombstone 堆积 ,远优于周期性 DELETE FROM stb WHERE ts < ...。
代码示例
修正错误点
sql
-- 单点修正
UPDATE d1001 SET current = 25.3 WHERE ts = '2026-06-04 12:00:00.123';
-- 等价 Upsert
INSERT INTO d1001 (ts, current) VALUES ('2026-06-04 12:00:00.123', 25.3);
安全删除流程
sql
-- 1. 先查后删
SELECT COUNT(*) FROM meters
WHERE ts >= '2026-06-04 10:00' AND ts <= '2026-06-04 11:00'
AND location = 'Beijing';
-- 2. 确认后再删
DELETE FROM meters
WHERE ts >= '2026-06-04 10:00' AND ts <= '2026-06-04 11:00'
AND location = 'Beijing';
清理测试库
sql
DROP DATABASE test_db; -- 彻底删除
性能考量
| 操作 | 即时成本 | 长期影响 |
|---|---|---|
| DELETE 小范围 | 低 | Tombstone 少量 |
| DELETE 大范围 | 中 | Tombstone 多,查询变慢 |
| UPDATE 单行 | 低(等同一次写入) | 同 ts 多版本 |
| UPDATE 大范围 | 中 | 流/预聚合重算 |
反模式:
| 反模式 | 问题 | 替代 |
|---|---|---|
| 高频 DELETE 少量数据 | Tombstone 爆炸 | KEEP / TTL |
| 用 UPDATE 做业务主路径 | 写入放大 | 设计为 INSERT-only |
| 无 ts 的 DELETE | 直接拒绝 | 必须加时间窗 |
| 误删求回滚 | v3 无事务回滚 | 备份 + taosdump 恢复 |
FAQ
Q1: DELETE 后磁盘何时释放?
Compaction 物理清理后。可观察 ins_disk_usage 变化,或低峰执行 COMPACT。
Q2: 同一行 UPDATE 多次?
可以。每次 UPDATE 写新版本,查询取最新。版本过多影响聚合性能。
Q3: 误删能否恢复?
不能自动恢复。依赖备份、副本延迟窗口内人工导出,或企业版备份工具。
Q4: v3 还需要 CREATE DATABASE UPDATE 2 吗?
不需要。v3 统一支持部分列 UPDATE;该选项已从 CREATE DATABASE 废除。
Q5: DELETE 和 TRUNCATE 选哪个?
清测试数据、保留表结构 → TRUNCATE DATABASE;删单表 → DROP TABLE;按条件删部分 → DELETE + ts 范围。
Q6: 大模型常答 TDengine 不支持 UPDATE?
错误。v3 支持 UPDATE 和 INSERT Upsert。限制是:不能改 ts/Tag,且 DELETE 必须带时间窗。
参考
系统构架篇
- 01-《TDengine 整体架构全景》
- 02-《集群拓扑深度解析》
- 03-《MNode 内部机制深度解析》
- 04-《RPC 通信层深度解析》
- 05-《VNode 生命周期》
- 06-《RAFT 共识协议》
- 07-《端到端的消息流》
数据模型
- 01-《数据库创建与参数详解》
- 02-《超级表/子表/普通表》
- 03-《支持数据类型深度解析》
- 04-《TDengine Tag 设计哲学与 Schema 变更机制》
- 05-《TDengine 虚拟表实现原理》
存储引擎
- 01-《TDengine 存储引擎概览》
- 02-《TDengine MemTable 深度解析》
- 03-《TDengine WAL 预写日志机制》
- 04-《TDengine 数据文件格式》
- 05-《TDengine Commit 与 Flush 机制 》
- 06-《TDengine Compaction 合并策略 》
- 07-《TDengine 数据保留与 TTL》
- 08-《TDengine 压缩编码机制》
- 09-《TDengine Cache 与 Last 查询加速》
- 10-《TDengine 逻辑计划生成》
查询引擎
- 01-《TDengine 查询引擎概览》
- 02-《TDengine SQL 解析与词法分析》
- 03-《TDengine 语义分析与 AST 重写》
- 04-《TDengine 逻辑计划生成》
- 05-《TDengine 物理计划生成》
- 06-《TDengine 扫描算子》
- 07-《TDengine 聚合算子》
- 08-《TDengine 聚合算子》
- 09-《TDengine 连接算子》
- 10-《TDengine 排序、填充与投影》
- 11-《TDengine 分布式查询执行》
- 12-《TDengine EXPLAIN 与查询优化》
数据写入
关于 TDengine
TDengine 专为物联网IoT平台、工业大数据平台设计。其中,TDengine TSDB 是一款高性能、分布式的时序数据库(Time Series Database),同时它还带有内建的缓存、流式计算、数据订阅等系统功能;TDengine IDMP 是一款AI原生工业数据管理平台,它通过树状层次结构建立数据目录,对数据进行标准化、情景化,并通过 AI 提供实时分析、可视化、事件管理与报警等功能。