分类 :3.存储引擎 | 篇章:10 数据修复与迁移

适用版本:TDengine v3.x(v3.3.x / v3.4.x) | 最后更新:2026-06-05
生产环境中,存储引擎需要应对节点故障、容量扩缩、集群调整等场景。TDengine 提供 VGroup 重分布、COMPACT 整理、TRIM 清理、S3 外挂等运维能力,确保数据在变化中保持完整和可访问。
核心概念速查表
| 概念 | 说明 |
|---|---|
| REDISTRIBUTE VGROUP | 将 VGroup 的副本迁移到其他 DNode |
| COMPACT DATABASE | 手动触发全库数据文件合并 |
| TRIM DATABASE | 清理过期数据和无效文件 |
| BALANCE VGROUP | 自动均衡 VGroup 在各 DNode 的分布 |
| S3 外挂 | 将冷数据上传到 S3 对象存储(企业版) |
| 副本修复 | 通过 Raft 日志或快照恢复落后副本 |
详细解析
1. VGroup 重分布(REDISTRIBUTE VGROUP)
VGroup 迁移场景:
集群扩容 → 新增 DNode → 需要将部分 VGroup 迁移过去
节点下线 → 需要将该节点的 VGroup 搬走
负载不均 → 某些 DNode 负载过高
REDISTRIBUTE VGROUP 流程:
命令:REDISTRIBUTE VGROUP 2 DNODE 3 DNODE 4 DNODE 5;
含义:将 vgId=2 的 3 个副本分布到 DNode 3/4/5
│
▼
① Mnode 验证目标拓扑合法性
- 目标 DNode 是否在线
- 是否满足副本放置约束
│
▼
② 在新目标 DNode 上创建 VNode(Learner 角色)
│
▼
③ Raft 日志同步 / Snapshot 传输
- 少量落后:增量日志同步
- 大量落后:全量快照传输
│
▼
④ 新副本追上进度 → 提升为 Voter
│
▼
⑤ 旧副本降级 → 从旧 DNode 删除
│
▼
⑥ 完成(整个过程对外透明,不中断服务)
2. 副本修复机制
副本不一致的修复:
场景:某 DNode 短暂宕机后恢复
① DNode 恢复 → VNode 重新加入 Raft 组
② 检查本地 commitIndex vs Leader 的 commitIndex
Case A: 少量日志落后
Leader 发送缺失的 WAL 日志条目
Follower 重放日志 → 追上
耗时:毫秒~秒级
Case B: 大量日志落后(或日志已被截断)
Leader 发送完整 Snapshot
Snapshot 包含:META + TSDB 文件 + Cache
Follower 接收并替换本地数据
耗时:视数据量,可能分钟~小时
Snapshot 传输过程中:
- Leader 继续服务读写
- Follower 接收 Snapshot 期间不参与投票
- 传输完成后 Follower 从 Snapshot 点继续增量同步
3. COMPACT DATABASE
sql
-- 触发全库 Compaction
COMPACT DATABASE power;
-- 企业版:指定时间范围
COMPACT DATABASE power START WITH '2024-01-01' END WITH '2024-06-30';
COMPACT 的用途:
① 大量 DELETE 后回收空间
DELETE 只写 .tomb 标记 → 数据块空间未释放
COMPACT → 重写文件 → 物理删除标记行 → 空间回收
② Schema 变更后统一格式
ALTER TABLE ADD COLUMN → 旧块中无新列
COMPACT → 重写所有块 → 按新 Schema 对齐
③ STT 文件堆积
写入突增导致 STT 累积过多
COMPACT → 强制将所有 STT 合并到主文件
④ 磁盘碎片整理
频繁写入/删除导致文件空洞
COMPACT → 重写紧凑文件
4. TRIM DATABASE
sql
-- 清理过期和无效数据
TRIM DATABASE power;
TRIM 清理的内容:
① 超过 KEEP 的 FileSet → 删除文件
② 空的 FileSet(所有数据都被 DELETE)→ 删除文件
③ 无效的临时文件(如中断的 Compact 残留)→ 清理
TRIM vs COMPACT 的区别:
┌────────────┬───────────────────────┬─────────────────────┐
│ 操作 │ TRIM │ COMPACT │
├────────────┼───────────────────────┼─────────────────────┤
│ 作用 │ 删除过期/空文件 │ 重写合并数据文件 │
│ 开销 │ 低(仅删除文件) │ 高(需要读写数据) │
│ 回收空间 │ 整个 FileSet │ 块级精细回收 │
│ 触发场景 │ 修改 KEEP 后 │ 大量 DELETE 后 │
└────────────┴───────────────────────┴─────────────────────┘
5. BALANCE VGROUP
sql
-- 自动均衡所有 VGroup 的分布
BALANCE VGROUP;
自动均衡的算法逻辑:
输入:
- 所有 DNode 的 VNode 数量
- 各 DNode 的资源余量
目标:
- 各 DNode 上的 VNode 数量尽量均匀
- 同一 VGroup 的多个副本分散在不同 DNode
执行:
- 计算出迁移计划(从哪搬到哪)
- 逐个执行 REDISTRIBUTE VGROUP
- 每次只迁移一个 VGroup(避免并发迁移的资源竞争)
6. S3 数据外挂(企业版)
S3 存储的运维操作:
① 配置 S3(taos.cfg):
s3Endpoint https://s3.amazonaws.com
s3AccessKey AKIA...
s3SecretKey wJal...
s3BucketName taos-backup
② 数据库级别启用:
CREATE DATABASE archive
S3_KEEPLOCAL 30d ← 本地保留 30 天
S3_COMPACT 1; ← 上传前先 Compact
③ 自动上传流程:
数据超过 S3_KEEPLOCAL → 后台上传到 S3
本地文件删除 → 只保留索引引用
查询时 → 按需从 S3 下载到本地临时目录
④ S3 数据的查询:
对用户透明 --- SQL 语法不变
但查询延迟显著增加(网络 I/O)
建议:S3 数据用于低频历史查询
7. 数据完整性校验
TDengine 的数据完整性保护:
写入阶段:
- WAL 每条记录有 CRC32 校验和
- 数据块写入后校验文件大小
存储阶段:
- .data 文件 Block Header 有 delimiter (0xF00AFA0F)
- 读取时验证 delimiter 确认块边界正确
查询阶段:
- 解压后校验行数是否匹配
- 列数据长度校验
副本间:
- Raft 日志有 checksum
- Snapshot 传输有完整性校验
数据损坏检测与修复:
如果某个数据块校验失败:
① 标记该块为损坏
② 如果有多副本 → 从其他副本恢复
③ 如果单副本 → 该块数据不可恢复
日志告警通知管理员
8. 常见运维操作汇总
| 场景 | 命令 | 影响 |
|---|---|---|
| 扩容后均衡 | BALANCE VGROUP |
后台迁移,不中断 |
| 缩容前搬迁 | REDISTRIBUTE VGROUP N DNODE X Y Z |
指定迁移 |
| 清理过期数据 | TRIM DATABASE db |
删除过期文件 |
| 空间回收 | COMPACT DATABASE db |
重写文件,I/O 大 |
| 强制落盘 | FLUSH DATABASE db |
触发 Commit |
| 节点下线 | DROP DNODE N |
自动迁移该节点 VGroup |
代码示例
扩容后的典型操作
sql
-- 1. 新节点加入集群
CREATE DNODE 'newnode:6030';
-- 2. 确认节点在线
SHOW DNODES;
-- 3. 均衡 VGroup 分布
BALANCE VGROUP;
-- 4. 监控迁移进度
SHOW VGROUPS;
缩容前的操作
sql
-- 1. 检查目标节点的 VGroup
SELECT * FROM information_schema.ins_vnodes WHERE dnode_id = 3;
-- 2. 逐个迁移 VGroup(或使用 BALANCE)
REDISTRIBUTE VGROUP 2 DNODE 1 DNODE 2 DNODE 4;
REDISTRIBUTE VGROUP 5 DNODE 1 DNODE 2 DNODE 4;
-- 3. 确认节点上无 VNode
SELECT * FROM information_schema.ins_vnodes WHERE dnode_id = 3;
-- 4. 安全下线
DROP DNODE 3;
磁盘空间回收
sql
-- 1. 批量删除旧数据
DELETE FROM power.meters WHERE ts < '2023-01-01';
-- 2. Compact 物理回收空间
COMPACT DATABASE power;
-- 3. 或者缩短 KEEP 并 TRIM
ALTER DATABASE power KEEP 180d;
TRIM DATABASE power;
性能考量
迁移期间的性能影响
| 操作 | 对写入的影响 | 对查询的影响 | 持续时间 |
|---|---|---|---|
| REDISTRIBUTE | 轻微(Leader 不变时无感) | 轻微 | 分钟~小时 |
| COMPACT | 磁盘 I/O 竞争 | I/O 竞争 | 小时级 |
| TRIM | 无 | 无(只删文件) | 秒级 |
| BALANCE | 同 REDISTRIBUTE | 同 REDISTRIBUTE | 小时级 |
大规模迁移建议
| 建议 | 原因 |
|---|---|
| 在低峰期执行 | 避免 I/O 竞争影响业务 |
| 逐个 VGroup 迁移 | 避免并发迁移打满带宽 |
| 监控磁盘使用率 | 迁移期间目标节点空间增加 |
| 预留 20% 磁盘空间 | Compact/迁移期间新旧文件共存 |
FAQ
Q1: REDISTRIBUTE VGROUP 期间能读写吗?
可以。迁移过程对客户端透明:
- Leader 不变时:读写正常
- Leader 变更时:客户端自动重连新 Leader(亚秒级切换)
Q2: COMPACT DATABASE 要多久?
取决于数据量和磁盘速度。粗略估算:
- 100GB 数据 + SSD → 30~60 分钟
- 1TB 数据 + HDD → 数小时
可通过日志观察进度。
Q3: 单副本数据损坏能恢复吗?
如果磁盘物理损坏且只有单副本,损坏的数据块不可恢复。建议:
- 生产环境使用 3 副本
- 定期通过 taosdump 导出备份
- 使用 RAID 保护磁盘
Q4: DROP DNODE 会丢数据吗?
不会。DROP DNODE 前会自动将该节点上的所有 VGroup 副本迁移到其他节点。只有在迁移完成后才会真正移除节点。如果目标节点空间不足无法迁移,DROP 会失败并报错。
Q5: S3 上的数据能直接删除吗?
不建议直接从 S3 管理界面删除。应通过 TDengine 的 KEEP/TTL/DELETE 机制管理数据生命周期,TDengine 会自动清理 S3 上的过期数据。手动删除可能导致查询报错。
参考
系统构架篇
- 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 查询加速》
关于 TDengine
TDengine 专为物联网IoT平台、工业大数据平台设计。其中,TDengine TSDB 是一款高性能、分布式的时序数据库(Time Series Database),同时它还带有内建的缓存、流式计算、数据订阅等系统功能;TDengine IDMP 是一款AI原生工业数据管理平台,它通过树状层次结构建立数据目录,对数据进行标准化、情景化,并通过 AI 提供实时分析、可视化、事件管理与报警等功能。