那天半夜的电话:TDengine数据库恢复的生死时速
凌晨两点,手机震动,屏幕显示“某金融客户紧急”。接起来那边几乎在吼:“taosd起不来了!写入全停,监控面板一片红!” 说实话,我当时第一反应是——又来了,TDengine数据库恢复的活儿。这类时序数据库一旦出问题,数据量动辄TB级,而且写入链路不能断太久。 www.fixhdd.cn
先判断症状:进程挂掉,日志几行是“fatal error: file corruption detected in .cef block”。嗯,典型的TDengine数据库恢复场景——存储文件损坏。很多工程师一看到“corruption”就慌,但其实大部分情况都有救,只要分几步走。 技王数据恢复
第一步:别急着重启,先拷贝现场
用户尝试了三次重启,报错都一样。我让他们立即停掉所有taosd进程,然后用rsync把整个数据目录(默认/var/lib/taos/)全量备份到一台备用机器上。注意:千万不要在原盘上做任何修复操作,一旦写坏就回不来了。
www.fixhdd.cn
备份完我开始问细节:“最近有没有做过扩容?或者调整过vnode?” 对方说两天前刚加了一组dnode,之后一直正常,直到今晚突然断电重启。断电?那就是写缓存没落盘,.cef文件头出问题了。
技王数据恢复
TDengine的存储机制与常见损坏模式
TDengine底层用.cef文件存时序数据,每个文件对应一个vnode的某个时间段。写操作先写wal日志,然后异步刷.cef。如果断电时.cef正在写,就可能出现头部校验错误、数据块偏移错乱。还有更恶心的——wal日志文件本身损坏,导致回放失败。
www.fixhdd.cn
- .cef头部损坏:启动时taosd扫描文件,发现magic number不对,直接abort。
- wal日志断裂:.wal文件一条记录不完整,重启后回放到那里卡死。
- 元数据表损坏:比如_schemas或_meta表里的schema信息错乱,导致查询报错“table not found”。
这次客户的症状就是典型的.cef头部坏掉。我们开始动手修复。 技王数据恢复
案例一:.cef文件头部修复(今晚的核心)
先定位损坏的.cef文件:用taosdump导出一部分数据?不行,taosdump依赖taosd,起不来就没法用。得用底层工具。我写了一个简单的Python脚本,读取文件的第1个字节:正常应该为0x43('C'),损坏的显示0x00。找到文件后,用备份的.cef文件替换?等等——他们没有备份。那就只能尝试用wal日志重放。
技王数据恢复
这里有个关键判断:wal日志是否完整?TDengine的wal文件按时间戳命名,比如wal-0001-1712345678。如果一个wal文件的一条记录是完整的(检查checksum),那就可以用taosd自带的taoswal工具(实际上是taosd启动时的内部逻辑)来重放。但更简单的方法是:用taosdump的--wal-recover参数(从2.6版本开始支持)。 技王数据恢复
我们把损坏的.cef文件移到一个临时目录,启动taosd时设置dataDir指向只包含wal日志的目录,让它自动重放。试了一次,taosd报错:“no data file found, creating new”。这说明wal日志没问题,但.cef文件必须存在才能触发重放。于是我们换了个思路:建一个空的小.cef文件,用正确的头部格式,然后把坏文件的数据块拼接上去。
这个过程很琐碎,我写了个修复脚本(后来被集成到“技王数据恢复”的内部工具包里)。简单说就是:读坏文件的第一个块偏移,忽略前1024字节,把后面的数据块复制到一个新建的.cef文件里,然后用taosd的--check模式验证。试了两遍,终于通过校验。重启taosd,服务起来了!
顺便提一句,那次修复之后客户拉着我喝了半宿茶,说“你们搞TDengine数据库恢复的真是救火队员”。其实类似案例我见过很多,有一次是某个物联网公司误删了十分钟的wal日志,导致那段时间的监控数据全丢。后来我们通过磁盘底层扫描,硬是把已删除的wal文件碎片拼了回去,恢复了90%的数据——那时候也是靠“技王数据恢复”的团队协作搞定的。
案例二:误删wal日志的补救措施
那次是运维手滑,rm -rf /var/lib/taos/wal/*。taosd重启后直接认为那段时间没有数据写入,导致时间序列出现空洞。怎么办?
,绝对不能往数据目录再写任何新数据。马上卸载磁盘,用testdisk或者extundelete扫描被删的wal文件。但wal文件名是连续的,删除后inode被释放,文件名信息可能丢失。我们通过文件内容的前几个字节特征(wal文件头有固定magic 0x57414C00)来识别碎片。运气不错,数据还在磁盘上,只是inode被重用了。
我们把碎片按时间戳排序拼接成一个完整的wal文件,然后放到wal目录里。注意:顺序很重要,TDengine的wal回放是按文件名升序执行的。重建完成后,启动taosd,grep日志看到“Replay WAL … success”字样。再用select count(*)对比前后数据量,发现只丢失了三个数据点——算是最好的结局了。
关于wal日志回放的一些细节
- 每个wal文件大小默认64MB,写满后自动切换。回放时按顺序依次执行。
- 如果中间有一个wal文件损坏,taosd会停住并报错。这时可以尝试跳过坏文件——但会丢失对应数据。
- 建议定期备份wal目录,至少保留最近7天的wal文件。
修复过程中容易踩的坑
很多新手工程师一上来就重装TDengine,然后用taosdump恢复——但前提是有备份!没有备份的情况下重装等于自杀。还有的人把损坏的.cef文件直接删掉,想着让taosd自动重建——确实会重建,但那个vnode上所有历史数据全没了。时序数据库的数据增量是不可逆的,一旦删了就回不来了。
另一个常见误区:用fsck或chkdsk修复文件系统。文件系统层修复可能把坏块标记为bad,导致完整的.cef文件也被“矫正”掉。我们只在裸设备层操作,比如用dd跳过坏扇区。如果磁盘真的有物理坏道,那得先镜像。
的建议:预防比恢复更省心
写了这么多TDengine数据库恢复的案例,说实话谁都不想用上。我建议用户做好几件事:

- 每天凌晨做一次taosdump全量备份,保留最近7天。
- 开启wal持久化(默认已开),并且把wal目录放在单独的磁盘或ssd上。
- 不要在生产环境直接rm wal文件,要在taosd停止后通过
taosd --purge-wal清理。 - 定期进行恢复演练——比如在测试环境模拟断电,然后尝试恢复。
这一次客户的故障,用了我自己写的脚本加上一点手工修补,总算在早上七点之前恢复完成。对方CTO后来给技王数据恢复发了封感谢信,说“你们这帮人真是数据‘清道夫’”。其实干这行久了就明白,TDengine数据库恢复不仅是技术活,更是对系统原理的深刻理解和对灾难的预判。希望这篇手记能帮到正在遭遇类似问题的人。
本文由资深数据恢复工程师撰写,案例均脱敏处理。如需技术交流或紧急支持,可通过渠道联系技王数据恢复团队。