TDengine 错误处理 — 错误码、异常传播、故障恢复

分类 :17.内部机制 | 篇章 :03 错误处理

免费详情

错误处理是数据库可靠性的基石。本文讲解 TDengine 的错误码体系、异常传播路径、故障恢复机制。

错误分类速查

类别 错误码范围 例子
通用 0x0001~0x00FF 内存不足
RPC 0x0100~0x01FF 连接断开
客户端 0x0200~0x02FF 无效连接
服务端通用 0x0300~0x03FF 节点不可用
元数据 0x0400~0x04FF 表不存在
查询 0x0700~0x07FF SQL 语法
同步 0x0900~0x09FF RAFT 错误
TSDB 0x0B00~0x0BFF 数据块损坏
权限 0x0E00~0x0EFF 权限不足

详细解析

1. 错误码设计

复制代码
错误码格式:
  
  uint32_t 32 位
  
  例:0x80000216
  
  高位 0x80000000:表示错误(与 0 区分)
  低位 0x216:具体错误
  
  
设计原则:
  - 全局唯一
  - 按模块分段
  - 易于排查
  - 客户端/服务端一致


典型错误码:
  
  0x00000000  成功
  0x80000003  Out of memory
  0x80000216  Invalid SQL
  0x80000220  Database not exist
  0x8000027C  Table does not exist
  0x80000408  Login disabled
  0x80000B07  Disk full

2. 错误传播路径

复制代码
错误产生 → 包装 → 传播 → 终端处理

例:查询不存在的表

  ① VNode 查询执行
       └─ 表不存在 → ERROR 0x8000027C
  
  ② 错误打包到 RPC 响应
       └─ 含错误码 + 错误描述
  
  ③ 客户端接收
       └─ 解包错误
  
  ④ 客户端 API 抛异常 / 返回错误
       └─ Python: raise exception
       └─ Java: throw SQLException
       └─ C: 返回非 0
  
  ⑤ 应用处理
       └─ 重试 / 上报 / 失败


关键设计:
  - 错误不被吞掉
  - 上下文信息保留
  - 链路追踪(QID)

3. 客户端错误处理

python 复制代码
# Python 异常处理
import taosws

try:
  conn = taosws.connect("...")
  conn.execute("SELECT * FROM not_exist_table")
except taosws.QueryError as e:
  print(f"Query error: {e}")
  print(f"Error code: {e.errno}")
except taosws.ConnectionError as e:
  print(f"Connection error: {e}")
  # 重连逻辑
except Exception as e:
  print(f"Other: {e}")
java 复制代码
// Java
try {
  Statement stmt = conn.createStatement();
  stmt.execute("SELECT * FROM bad_table");
} catch (SQLException e) {
  int errorCode = e.getErrorCode();
  String sqlState = e.getSQLState();
  
  if (errorCode == 0x027C) {
    // 表不存在
  } else if (sqlState.startsWith("08")) {
    // 连接相关
    reconnect();
  }
}
go 复制代码
// Go
_, err := db.Query("SELECT * FROM bad_table")
if err != nil {
  if taosErr, ok := err.(*taosError.Error); ok {
    fmt.Printf("TDengine error: %d, %s\n", taosErr.Code, taosErr.Message)
  }
}

4. 重试策略

复制代码
可重试错误:

  ✓ 网络瞬断
  ✓ Leader 切换中
  ✓ 节点临时不可用
  ✓ 超时
  ✓ "Sync timeout"


不可重试错误:

  ✗ SQL 语法错误
  ✗ 表不存在
  ✗ 权限不足
  ✗ 数据类型不匹配
  ✗ 参数错误


重试模式:

  指数退避:
    第 1 次:100ms
    第 2 次:200ms
    第 3 次:400ms
    最多 5 次
    
  示例:
    delay = 100
    for attempt in range(5):
      try:
        return execute(sql)
      except RetryableError:
        sleep(delay / 1000)
        delay *= 2
    raise TimeoutError

5. 服务端故障恢复

复制代码
节点重启恢复:

  ① 启动时检查 WAL
     - 重放未持久化的写入
     - 恢复内存表
     
  ② 加入集群
     - 注册到 MNode
     - 报告状态
     
  ③ VNode 副本同步
     - RAFT 协议补齐落后日志
     - 状态机一致后服务


VNode 故障恢复:

  ① Leader 失效检测(心跳超时)
  ② Follower 触发选举
  ③ 新 Leader 产生
  ④ 客户端重路由
  ⑤ 服务恢复(秒级)
  

数据块损坏:

  ① 校验失败检测
  ② 标记损坏
  ③ 从其他副本恢复
  ④ 严重情况报警

6. 内存/磁盘异常

复制代码
OOM 处理:

  ① 内部限流
     - 拒绝新请求
     - 释放缓存
  
  ② OOM Killer
     - 进程被杀
     - systemd 重启
  
  ③ 重启恢复
     - 重放 WAL
     - 数据完整


磁盘满:

  ① 写入预检
     - 检测剩余空间
     - 不足则拒绝
  
  ② 错误码 0x80000B07 Disk full
  
  ③ 客户端处理
     - 应用降级
     - 告警通知运维
  
  ④ 运维清理
     - 清旧日志
     - 数据归档
     - 扩容

7. 错误日志

复制代码
日志位置:
  /var/log/taos/taosdlog.0


错误格式:
  时间 进程ID 级别 模块 函数 错误码 描述
  
  示例:
  2026-06-04 12:00:00 [12345] ERROR VND vnodeOpen 
    code:0x80000300 desc:vnode not exist


关键字搜索:
  grep -i error /var/log/taos/taosdlog.0
  grep "0x80000" /var/log/taos/taosdlog.0


调试模式:
  ALTER DNODE 1 'debugFlag' '143';
  # 临时启用 debug
  
  ALTER DNODE 1 'debugFlag' '131';
  # 改回 error+warn

8. 错误码查询

sql 复制代码
-- 查所有错误码(系统表)
SELECT * FROM information_schema.ins_errors;
-- 部分版本支持


-- 命令行查询
# taos --help | grep error


-- 文档查询
# https://docs.taosdata.com/reference/error-code/


-- 源码定义
# include/util/taoserror.h
# 但本文不深入源码细节

代码示例

健壮的客户端封装

python 复制代码
import taosws
import time
import logging

class RobustClient:
  RETRYABLE_CODES = {
    0x80000300,  # node not available
    0x80000310,  # leader switch
    0x80000316,  # timeout
  }
  
  def __init__(self, dsn, max_retries=3):
    self.dsn = dsn
    self.max_retries = max_retries
    self.conn = None
    self._connect()
  
  def _connect(self):
    self.conn = taosws.connect(self.dsn)
  
  def execute(self, sql):
    last_err = None
    delay = 0.1
    
    for attempt in range(self.max_retries):
      try:
        return self.conn.execute(sql)
      
      except taosws.QueryError as e:
        last_err = e
        if e.errno not in self.RETRYABLE_CODES:
          raise  # 不可重试
        logging.warning(f"Retry {attempt+1}: {e}")
        time.sleep(delay)
        delay *= 2
      
      except taosws.ConnectionError as e:
        last_err = e
        logging.warning(f"Reconnecting: {e}")
        try:
          self._connect()
        except:
          time.sleep(delay)
          delay *= 2
    
    raise last_err

监控错误统计

sql 复制代码
-- 通过日志聚合(需 ELK 或类似)
-- 或扫描日志文件统计

-- 错误码分布
SELECT error_code, COUNT(*) AS cnt 
FROM log_index 
WHERE level='ERROR' AND ts > NOW - 1d 
GROUP BY error_code 
ORDER BY cnt DESC;


-- 客户端错误监控(应用层)
# 应用上报到 Prometheus / log 数据库
COUNTER tdengine_errors_total{code="...", db="..."}

性能考量

错误处理开销

场景 开销
正常路径 几乎为零
错误抛出 微秒级
异常解析 几十微秒
重试 + 退避 视延迟

重试导致放大

重试可能放大问题。建议:

  • 限制重试次数
  • 退避避免雪崩
  • 监控重试率
  • 熔断保护下游

FAQ

Q1: 错误码定义在哪里?

服务端:内核内部定义。

客户端:通常通过 SDK 头文件/常量定义获取。

文档:官方错误码列表。

Q2: 怎么区分可重试?

  • 网络/超时类:可重试
  • 业务错误(SQL/数据):不重试
  • 节点状态变化:可重试

Q3: 怎么调试错误?

  1. 查错误码含义
  2. 查服务端日志(按时间)
  3. 启用 debug 日志
  4. 用 QID 串联客户端到服务端日志

Q4: 客户端连接断开自动恢复吗?

WebSocket 客户端通常内置重连。Native 需应用层处理。

Q5: 写入失败数据丢吗?

视失败时机:

  • WAL 写入前失败:丢
  • WAL 写入后失败:自动恢复
  • 副本未达成共识:可能丢(少见)
    建议应用层有写入确认+重试。

参考

系统构架篇

数据模型

存储引擎

查询引擎

数据写入

数据订阅

预聚合

索引

SQL 语句

客户端与连接器

运维

安全

生态

应用案例

产品对比

内部机制

关于 TDengine

TDengine 专为物联网IoT平台、工业大数据平台设计。其中,TDengine TSDB 是一款高性能、分布式的时序数据库(Time Series Database),同时它还带有内建的缓存、流式计算、数据订阅等系统功能;TDengine IDMP 是一款AI原生工业数据管理平台,它通过树状层次结构建立数据目录,对数据进行标准化、情景化,并通过 AI 提供实时分析、可视化、事件管理与报警等功能。

相关推荐
zbyyd1 小时前
Linux 系统编程 :select/epoll 多路复用与 SQLite 数据库实战
linux·数据库·sqlite
俊昭喜喜里1 小时前
c#中的构造函数
开发语言·数据库·c#
虎王物联1 小时前
Docker BuildKit多阶段构建:IoT固件交叉编译流水线实战
运维·物联网·ci/cd·docker·容器·物联网嵌入式
养生技术人1 小时前
Oracle OCP认证考试题目详解082系列第17题
运维·数据库·sql·oracle·ocp
koi77u1 小时前
嵌入式学习———sqlite数据表
linux·数据库·学习·sqlite
xx~t1 小时前
嵌入式——Linux软件编程——数据库
linux·c语言·数据库·oracle·sqlite
ACP广源盛139246256731 小时前
M6/M5 Pro Mac mini 端侧 AI 爆发@ACP#YLB3118 存储扩展芯片在本地 AI 服务中的机会与落地场景
大数据·网络·数据库·人工智能·嵌入式硬件·macos
隔窗听雨眠2 小时前
关系型数据库长期可维护性完全指南:设计、索引、运维、安全的系统性实践
数据库
IT研究室2 小时前
最新大数据毕业设计选题推荐-基于大数据的水质多指标关联分析与可视化的设计与实现-大数据-Spark-Hadoop-Bigdata
大数据·spark·课程设计