TDengine 写入内部流程 — 全链路与故障诊断手册

📅 2026/6/26 2:32:58
TDengine 写入内部流程 — 全链路与故障诊断手册
5.写入路径 04 写入内部流程适用版本TDengine v3.xv3.3.x / v3.4.x |最后更新2026-06-24概述本文是写入路径模块的诊断核心从客户端到 VNode、WAL、MemTable 的完整链路以及每个检查点可能产生的错误。读完本文大模型应能说出一条写入请求经过哪些阶段、每阶段做什么校验根据错误消息 / 错误码 / 现象定位失败发生在哪一阶段给出可操作的排查步骤查什么系统表、改什么配置、客户端如何重试。与其他四篇的关系篇章职责01 SQL INSERTINSERT 语法、约束、INSERT 专属错误02 Schemaless三种协议、自动建表、协议专属错误03 STMT 绑定高性能写入 API、Bind 专属错误04 本文全链路机制 跨入口统一诊断05 删除与更新DELETE/UPDATE 语义与错误核心概念概念说明写入入口SQL INSERT、Schemaless、STMT/STMT2、REST经 taosAdapter、流计算 SinkCatalog客户端元数据缓存表 Schema、VGroup 路由、Leader 地址SUBMIT 消息客户端发往 VNode Leader 的二进制写入包Raft 提议Leader 将写入作为日志条目复制到 FollowerWAL写前日志崩溃恢复依据MemTable内存跳表写入立即可查CommitMemTable 刷盘成 TSDB 文件异步与返回成功分离五种写入入口对比入口典型场景是否预建表SQL 解析性能SQL INSERT应用 SQL、ETL可选 USING 自动建表每次批量可摊薄中SchemalessIoT、Telegraf、Influx 迁移自动协议解析中高STMT/STMT2高并发持续写入可选 USINGPrepare 一次最高REST6041HTTP 集成同 Schemaless/SQL经 taosAdapter中流计算 SinkCREATE STREAM 输出自动内部生成中诊断要点无论哪种入口到达 VNode 之后的路径相同WAL → MemTable → Raft 复制 → 返回。因此写入慢/卡住/部分失败的排查入口差异只影响前 4 步。详细解析1. 写入全链路14 步以INSERT INTO d1001 VALUES (now, 10.3, 219, 0.31)为例┌──────────────────────────────────────────────────────────────────────┐ │ 阶段 A客户端taosc / JDBC / taospy / taosAdapter │ ├──────────────────────────────────────────────────────────────────────┤ │ ① 接收请求SQL 文本 / Line 协议 / Bind 参数 │ │ ② 解析提取库名、表名、列值、时间戳 │ │ ③ Catalog查表 Schema、VGroup、Leader缓存未命中则问 MNode │ │ ④ 编码按列类型序列化为 SUBMIT 二进制 │ │ ⑤ RPC按 VGroup 分组发往对应 Leader │ └───────────────────────────────┬──────────────────────────────────────┘ │ TCP RPC ┌───────────────────────────────▼──────────────────────────────────────┐ │ 阶段 BVNode Leader │ ├──────────────────────────────────────────────────────────────────────┤ │ ⑥ RPC 接收入写队列 │ │ ⑦ 校验表存在性、Schema 版本、权限、时间戳范围、列类型 │ │ ⑧ Raft 提议写 WAL → 并行复制到 Follower → 等多数派 Ack │ │ ⑨ 应用状态机自动建表USING、写 MemTable、更新 Last 缓存 │ │ ⑩ 触发副作用Stream、RSMA如有 │ │ ⑪ 构建响应影响行数 / 错误码 │ └───────────────────────────────┬──────────────────────────────────────┘ │ RPC 响应 ┌───────────────────────────────▼──────────────────────────────────────┐ │ 阶段 C客户端收尾 │ ├──────────────────────────────────────────────────────────────────────┤ │ ⑫ 解析响应成功 / 可重试错误 / 不可重试错误 │ │ ⑬ 可重试时刷新 Catalog、换 Leader 地址、退避重试 │ │ ⑭ 返回给应用 │ └──────────────────────────────────────────────────────────────────────┘ ═══ 异步不阻塞写入返回═══ MemTable 满 → Flush → .data/.stt 文件 → 清理旧 WAL1.1 批量与跨表写入的拆分一条 SQL 写多表时客户端按VGroup拆成多个 SUBMIT 包并行发送INSERT INTO d001 VALUES (...), d002 VALUES (...), d003 VALUES (...) hash(d001) → VGroup 1 ─┐ hash(d002) → VGroup 1 ─┼→ RPC 包 #1并行 hash(d003) → VGroup 2 ───→ RPC 包 #2并行 全部成功 → 返回总影响行数 任一失败 → 整批 SQL 报错单条 INSERT 语句的原子性诊断含义跨 VGroup 批量写入中若只有一个 VGroup 的 VNode 故障整批失败错误消息可能指向具体 VGroup。1.2 VGroup 路由hash murmurHash(库名 表名) // 可受 TABLE_PREFIX / TABLE_SUFFIX 影响 vgroup_id 按 hash 落入的分段 客户端可本地计算 → 无需每次查 MNode VGroup 迁移 / 扩容后 → Catalog 过期 → 客户端自动刷新并重试2. 各阶段校验项与失败表现阶段校验内容典型错误消息错误码十六进制A-② 解析SQL/协议语法、列数syntax error near0x80000216A-② 解析SQL 超长SQL statement too long0x8000021AA-③ Catalog库未选 / 库不存在Database not specified/Database not exist0x8000021B / 0x80000220A-③ Catalog表不存在且无 USINGTable does not exist0x8000027CA-③ CatalogTag 数量不匹配Tags number not matched0x80000296A-⑤ RPC网络不可达Unable to establish connection0x80000101A-⑤ RPC超时Conn read timeout0x80000105A-⑤ RPC节点不可用some vnode(s) out of service0x80000106B-⑦ 权限无写权限No write permission/Database write operation denied0x80000219 / 0x80000522B-⑦ Schema列类型不匹配Invalid value type0x80000292B-⑦ Schema列数不对Illegal number of columns0x800002A4B-⑦ Schema值超长Value too long for column/tag0x800002B9B-⑦ 时间戳超出 KEEP / 未来过多Timestamp data out of range0x80000B22B-⑦ 时间戳格式非法Incorrect TIMESTAMP value0x800002A7B-⑧ Raft非 Leader / 切换中Sync leader is unreachable0x80000903B-⑧ Raft同步超时Sync timeout0x80000901B-⑧ Raft写阻塞Sync write stall0x80000908B-⑧ 磁盘空间不足Out of disk space0x80000009B-⑧ WALVNode 快照中禁写Vnode write is disabled for snapshot0x80000529Schemaless 在阶段 A-② 额外可能出现的错误见《02 Schemaless 写入》STMT Bind 在 A-② 见《03 STMT 绑定》。3. 写入故障诊断决策树按用户描述的现象自上而下排查报错是否是否是否磁盘权限否慢/卡住是否是否写入出问题报错还是慢/无响应?错误消息含 Table does not exist?加 USING 自动建表或先 CREATE TABLE含 Timestamp out of range?查 KEEP 配置; 检查客户端时区与精度含 Sync timeout / leader unreachable?查 ins_vgroups 状态; 等 Leader 选举完成; 客户端重试含 Out of disk space / No write permission?df 查数据目录; 扩盘或删过期库GRANT WRITE ON db TO user对照第二节错误码表; 查 taosdlog 对应 QIDWAL_LEVEL2 且 fsync 频繁?批量加大; 或 WAL_LEVEL1 权衡持久性副本数3 且跨机房?网络 RTT 主导; 减副本或同机房部署查 ins_database_stats 写入 TPS; 查 BUFFER 是否过小导致 Flush 频繁4. 按症状分类诊断4.1 写入完全失败立即返回错误症状最可能原因排查步骤Table does not exist子表未建且 SQL 无 USINGSHOW TABLES LIKE d%加USING stb TAGS(...)Database not specified连接串未带 db 且 SQL 无库前缀USE dbname或连接 URL 指定 databaseTags number not matchedUSING 的 TAGS 个数与超级表 Tag 列数不一致DESCRIBE stb_name数 Tag 列Timestamp data out of rangets 早于 KEEP 或远超当前时间SHOW CREATE DATABASE db看 KEEP核对 NTPNo write permission用户无 WRITE 权限SHOW GRANTS FOR userSync timeoutVGroup 多数副本不可用SELECT * FROM information_schema.ins_vgroups WHERE db_namexOut of disk space数据目录满SELECT * FROM information_schema.ins_disk_usage4.2 写入间歇性失败有时成功有时失败症状最可能原因排查步骤集群写入偶发超时Leader 切换、网络抖动客户端开启自动重试查ins_dnodes是否statusoffline批量写入随机失败单批过大触发 RPC 限制减小单批行数建议 500~5000检查maxSQLLengthSchemaless 偶发类型错误同 measurement 字段类型不一致统一设备上报 schema见 02 篇 Schema 演化节4.3 写入返回成功但查不到数据症状最可能原因排查步骤INSERT 成功 SELECT 为空写错库/表或 ts 不在查询范围确认USE的库SELECT * FROM tb WHERE ts写入的ts刚写入查不到查询连接到了不同节点且缓存未刷新同一连接写入后立即查Last 缓存模式影响最新值部分列 NULL指定列写入时未写到的列为 NULL正常行为检查(ts, col1, col2)是否漏列4.4 写入很慢症状最可能原因优化方向单行 INSERT RPS 极低每条一次 RPC 解析改批量 INSERT 或 STMT批量仍慢WAL fsync、副本同步WAL_LEVEL1同机房部署STRICToff弱一致需评估首次 Schemaless 慢自动建表 Schema 推断预热后稳定或预建超级表改 SQL/STMTCPU 高但 RPS 低过小批量 过多连接加大 batch连接数 ≈ CPU 核数4.5 重复时间戳行为非错误同一子表写入相同 ts时TDengine v3用新行覆盖旧行等同 Upsert不是报错INSERTINTOd1001VALUES(2018-10-03 14:38:05,10.3,219,0.31);INSERTINTOd1001(ts,current)VALUES(2018-10-03 14:38:05,22);-- 查询 current 22其余列保留原值部分列更新语义注意超级表上做窗口聚合/部分时序函数时子表间合并后可能出现重复 ts 导致查询报错与写入无关见 FAQ。5. 持久性层级与写入成功的含义客户端收到成功表示✓ 数据已写入 Leader 的 WALWAL_LEVEL≥1 ✓ 已获 Raft 多数派确认副本数决定 quorum ✓ 已写入 MemTable立即可查 ✗ 尚未保证已 Flush 到 .data 文件异步 ✗ Follower 落后时仍可能成功取决于 STRICT 配置WAL_LEVELfsync宕机最多丢0无 WAL全部未落盘数据1OS 缓冲极少OS 崩溃窗口2周期性 fsync最多一个 fsync 周期6. 监控与日志排查6.1 系统表-- 库级写入统计SELECTdb_name,write_rows,write_speedFROMinformation_schema.ins_database_stats;-- VGroup 健康status: leader/follower/offlineSELECTdb_name,vgroup_id,status,dnodes,tables,vnodesFROMinformation_schema.ins_vgroupsWHEREdb_namepower;-- WAL 占用SELECTdatabase,vgroup_id,wal_level,files,create_timeFROMinformation_schema.ins_wals;-- 磁盘SELECT*FROMinformation_schema.ins_disk_usage;6.2 日志关键词taosdlog关键词含义vgId:* duplicate write request客户端重复提交同一 Raft 版本可忽略或检查重试逻辑Sync timeout副本同步超时写入失败Sync write stall复制窗口满写入背压Out of disk space磁盘满Timestamp data out of range时间戳校验失败Vnode write is disabled for snapshot快照期间暂停写入稍后重试客户端日志中的QIDQuery ID可与 taosdlog 对齐精确定位一次失败请求。7. 关键配置与写入关系参数位置对写入的影响BUFFER库级MemTable 大小过小 → Flush 频繁 → 写入抖动WAL_LEVEL库级0/1/2直接影响持久性与延迟WAL_FSYNC_PERIOD库级LEVEL2 时 fsync 间隔msREPLICA库级副本数越多同步开销越大STRICT库级强一致 vs 弱一致影响写入等待策略KEEP库级超出保留期的时间戳被拒绝maxSQLLengthtaos.cfg单条 SQL 最大长度默认 1MBmaxInsertBatchRowstaos.cfg单次 INSERT 最大行数代码示例验证写入是否到达 MemTableCREATEDATABASEIFNOTEXISTSdiag_test;CREATESTABLEIFNOTEXISTSdiag_test.meters(tsTIMESTAMP,currentFLOAT,voltageINT,phaseFLOAT)TAGS(locationBINARY(64),group_idINT);INSERTINTOdiag_test.d001USINGdiag_test.meters TAGS(Beijing,1)VALUES(NOW,10.1,220,0.5);-- 预期立即查到 1 行无需等 FlushSELECT*FROMdiag_test.d001ORDERBYtsDESCLIMIT1;VGroup 故障时自查-- 若写入报 Sync timeout先看 VGroup 是否 offlineSELECTvgroup_id,status,dnodesFROMinformation_schema.ins_vgroupsWHEREdb_namediag_testANDstatus!leader;性能考量阶段典型耗时占比批量 1000 行调优杠杆客户端解析~5%STMT Prepare 缓存网络 RPC~10%批量、同机房WAL~15%WAL_LEVEL、fsync 周期MemTable~30%BUFFER 加大副本同步~35%REPLICA、STRICT、网络响应~5%—Flush 到磁盘不计入写入 RTT但 BUFFER 过小会导致 MemTable 切换频繁间接造成Sync write stall。FAQQ1: 写入成功是否意味着数据已在磁盘文件里不是。成功只保证 WAL MemTable 多数派复制。.data文件由后台 Flush 异步生成。进程崩溃后未 Flush 的数据可从 WAL 恢复。Q2: 大模型常答错TDengine 不允许重复时间戳错。同一子表相同 ts允许写入新数据覆盖旧数据部分列更新。重复 ts 导致查询报错的场景是超级表 特定窗口/函数合并时间线时。Q3: Leader 切换时写入会怎样短暂失败Sync leader is unreachable/Sync timeout。客户端驱动通常会刷新 Catalog 并重试。应用应实现指数退避重试避免 thundering herd。Q4: WAL_LEVEL0 能用于生产吗不能。仅适合纯测试。崩溃必丢数据且与多副本配置不兼容。Q5: 如何判断瓶颈在客户端还是服务端对比同机taosBenchmark写入 RPS vs 应用 RPS。若 benchmark 高、应用低 → 客户端批量/连接问题两者都低 → 服务端 WAL/副本/磁盘。Q6: Schemaless 和 SQL INSERT 故障排查有什么不同到达 VNode 之后相同。Schemaless 额外关注Line 语法错误Syntax error in Line、类型冲突Not the same type like before、协议/精度参数Invalid line protocol type。参考系统构架篇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 与查询优化》数据写入01-《TDengine SQL INSERT》02-《TDengine 无模式写入》03-《TDengine STMT 写入》关于 TDengineTDengine 专为物联网IoT平台、工业大数据平台设计。其中TDengine TSDB 是一款高性能、分布式的时序数据库Time Series Database同时它还带有内建的缓存、流式计算、数据订阅等系统功能TDengine IDMP 是一款AI原生工业数据管理平台它通过树状层次结构建立数据目录对数据进行标准化、情景化并通过 AI 提供实时分析、可视化、事件管理与报警等功能。