TDengine 集群异常恢复:KILL CONNECTION / KILL QUERY / KILL TRANSACTION 与 RESET QUERY CACHE 实战指南
【免费下载链接】TDengineHigh-performance, scalable time-series database designed for Industrial IoT (IIoT) scenarios项目地址: https://gitcode.com/GitHub_Trending/tde/TDengine
在 TDengine 生产环境中,连接可能进入错误状态、查询可能长时间无法结束、元数据事务可能卡在中间阶段,多客户端环境下还可能出现客户端元数据不同步的问题。本文基于官方文档《异常恢复》(04-recovery.md),系统讲解 TDengine 提供的四条恢复语句——KILL CONNECTION、KILL QUERY、KILL TRANSACTION与RESET QUERY CACHE——的语法、参数获取方式与适用场景,并结合 mnode、parser 与 client 三层源码说明这些语句在系统内部的真实处理链路,帮助读者掌握"先定位、再终止、后验证"的完整异常恢复操作方案。
异常恢复语句总览
TDengine 用下列语句终止对应连接或任务,使系统恢复正常:
| 语句 | 作用对象 | 标识获取方式 | 语句节点(源码) |
|---|---|---|---|
KILL CONNECTION conn_id; | 指定连接 | SHOW CONNECTIONS | QUERY_NODE_KILL_CONNECTION_STMT |
KILL QUERY 'kill_id'; | 指定查询/写入任务 | SHOW QUERIES | QUERY_NODE_KILL_QUERY_STMT |
KILL TRANSACTION trans_id; | 指定元数据事务 | SHOW TRANSACTIONS | QUERY_NODE_KILL_TRANSACTION_STMT |
RESET QUERY CACHE; | 当前客户端的查询/元数据缓存 | 无需参数 | QUERY_NODE_RESET_QUERY_CACHE_STMT |
从源码结构看,这四类语句在 parser 阶段被翻译为对应的查询节点,前三类会构造发往 mnode(管理节点)的消息:parTranslater.c 中可见KILL CONNECTION构造TDMT_MND_KILL_CONN消息(L22531)、KILL QUERY构造TDMT_MND_KILL_QUERY(L22555)、KILL TRANSACTION构造TDMT_MND_KILL_TRANS(L22561),节点分发逻辑位于 parTranslater.c。而RESET QUERY CACHE走的是客户端本地处理路径(见 clientImpl.c 与 command.c),不依赖 mnode。
第一步:定位目标——用 SHOW 与性能视图获取 ID
执行 KILL 系列语句前,必须先拿到目标对象的 ID。TDengine 提供SHOW命令获取简要系统信息,更完整的字段可查询INFORMATION_SCHEMA与PERF_CONNECTIONS/PERF_QUERIES/PERF_TRANS等性能统计视图(视图定义见 性能数据视图 与 元数据视图)。
SHOW CONNECTIONS 与 conn_id
SHOW CONNECTIONS;显示当前系统中的连接信息(详见 SHOW CONNECTIONS)。对应PERF_CONNECTIONS视图的关键列包括:
| 列名 | 数据类型 | 说明 |
|---|---|---|
conn_id | UINT | 连接 ID(即KILL CONNECTION的参数) |
`user` | BINARY(24) | 用户名。关键字列,查询时需反引号转义 |
app | BINARY(24) | 客户端名称 |
pid | UINT | 发起该连接的客户端进程号 |
end_point | BINARY(134) | 客户端地址 |
login_time | TIMESTAMP | 登录时间 |
last_access | TIMESTAMP | 最后更新时间 |
type | BINARY(16) | 连接类型 |
token | BINARY(32) | 令牌名称(若使用令牌登录) |
完整 13 列定义见 PERF_CONNECTIONS。定位"异常连接"时,可结合pid、end_point、last_access与客户端进程做交叉比对:长时间无活动(last_access陈旧)且占用资源不释放的连接即为候选终止对象。
SHOW QUERIES 与 kill_id
SHOW QUERIES;显示当前系统中正在进行的写入(更新)、查询、删除操作信息(详见 SHOW QUERIES)。对应PERF_QUERIES视图的关键列包括:
| 列名 | 数据类型 | 说明 |
|---|---|---|
kill_id | VARCHAR(26) | 用于KILL QUERY的 ID(直接作为语句参数) |
query_id | UBIGINT | 查询 ID |
conn_id | UINT | 连接 ID |
user/end_point | VARCHAR | 用户名与客户端地址 |
create_time | TIMESTAMP | 查询创建时间 |
exec_usec | BIGINT | 已执行时间(微秒),判断"耗时过长"的直接依据 |
stable_query/sub_query/sub_num | BOOL/INT | 是否超级表查询、是否子查询、子查询数量 |
sub_status | VARCHAR(1000) | 子查询状态(含子查询 ID、状态及该状态开始时间) |
`sql` | VARCHAR(2048) | SQL 语句。关键字列,查询时需反引号转义 |
phase_state | VARCHAR(64) | 查询当前阶段 / 状态 |
phase_start_time | TIMESTAMP | 当前阶段开始时间 |
完整 18 列定义见 PERF_QUERIES。实操中建议按exec_usec排序或过滤出执行时间异常的记录,同时用`sql`列确认 SQL 文本与业务归属后再执行 KILL。
SHOW TRANSACTIONS 与 trans_id
SHOW TRANSACTIONS; SHOW TRANSACTION transaction_id;SHOW TRANSACTIONS显示当前正在执行的元数据事务列表(针对除普通表以外的元数据级操作);SHOW TRANSACTION transaction_id显示指定事务的动作明细(详见 SHOW TRANSACTIONS)。对应PERF_TRANS视图的关键列包括:
| 列名 | 数据类型 | 说明 |
|---|---|---|
id | BIGINT | 事务编号(即KILL TRANSACTION的参数) |
create_time | TIMESTAMP | 创建时间 |
stage | VARCHAR(12) | 当前阶段(如redoAction、undoAction、commit) |
oper | VARCHAR(22) | 操作者 |
db/stable | VARCHAR | 相关数据库 / 超级表 |
killable | VARCHAR(10) | 是否可终止(KILL 前应先确认该列) |
failed_times | INT | 执行失败总次数 |
last_exec_time | TIMESTAMP | 上次执行时间 |
last_action_info | VARCHAR(511) | 上次执行失败明细 |
完整 11 列定义见 PERF_TRANS。若需排查历史残留,还可查询INS_TRANSACTION_LOGS(已完成事务的历史记录)与INS_TRANSACTION_ORPHANS(孤儿事务检测结果)视图。
终止连接:KILL CONNECTION
KILL CONNECTION conn_id;conn_id可通过SHOW CONNECTIONS获取。适用场景:某客户端连接进入错误状态(如半开连接、协议状态机卡死)持续占用服务端资源,且客户端侧已无法自行恢复时,由管理员在服务端强制断开。
源码级处理链路
- mnode 消息注册:mndProfile.c 中 mnode 启动时注册了
TDMT_MND_KILL_QUERY→mndProcessKillQueryReq与TDMT_MND_KILL_CONN→mndProcessKillConnReq两个处理器。 - 连接对象处理:
mndProcessKillConnReq(mndProfile.c)先通过mndCheckOperPrivilege校验操作者是否具备MND_OPER_KILL_CONN权限,然后在mnode的连接缓存(connCache)中按connId查找连接对象;若连接不存在则报错conn not exist,存在则将pConn->killed置 1。 - 心跳通知断开:被标记
killed的连接在下一次心跳响应中收到killConnection = 1标志(mndProfile.c),客户端据此主动断开。可以推断这是一种"软终止"机制:mnode 不直接拆掉 TCP 连接,而是借助周期性心跳把终止意图送达客户端,由客户端完成收尾,从而保证客户端状态机一致。
终止查询:KILL QUERY
KILL QUERY 'kill_id';kill_id可通过SHOW QUERIES返回的kill_id列直接获取。适用场景:某条大查询、删除或写入任务执行时间远超预期(可依据PERF_QUERIES.exec_usec判断),阻塞了业务窗口,需要强制中断。
kill_id 的内部结构
从源码看,kill_id是"连接 ID + 查询 ID"的组合串。mnode 处理函数mndProcessKillQueryReq(mndProfile.c)的处理逻辑为:
- 反序列化
SKillQueryReq,取出queryStrId(即kill_id字符串); - 校验
MND_OPER_KILL_QUERY权限; - 以冒号
:将queryStrId拆分为两段,前半段按 16 进制解析为connId,后半段解析为queryId(格式非法时记invalid QID错误日志); - 按
connId在连接缓存中取连接对象(不存在则报conn not exist),然后将pConn->killId设为目标queryId。
终止的生效路径
mnode 本身不直接杀查询执行线程,而是把killId记录在连接对象上;下一次客户端与服务端的心跳中,mnode 将该值写入rspBasic->killRid并清零本地记录(mndProfile.c),客户端收到后中断对应queryId的执行。因此KILL QUERY的生效时延取决于心跳周期,属于协作式取消;这也解释了为什么实践中 KILL 后个别长任务不会在毫秒级立即消失,而是等待下一次心跳确认后退出。
终止事务:KILL TRANSACTION
KILL TRANSACTION trans_id;trans_id可通过SHOW TRANSACTIONS获取。适用场景:元数据级事务(建库建表、用户/权限变更等,针对除普通表以外的元数据操作)在redoAction/undoAction/commit等阶段反复重试仍无法推进,持续占用 mnode 事务队列时,可由管理员强制终止。
源码级处理链路
KILL TRANSACTION语句经 parser 构造TDMT_MND_KILL_TRANS消息(parTranslater.c)投递到 mnode 处理。KILL 前建议先确认PERF_TRANS.killable列指示事务是否可终止、failed_times与last_action_info指示失败原因,避免误杀正常重试中的事务。
另外可以说明的是,TDengine 对"超时事务"另有自动回收路径:mnode 心跳逻辑中检测到事务超时后,会通过心跳键值HEARTBEAT_KEY_TXN_KILLED通知客户端将事务转入UTXN_STAGE_TIMEOUT_KILLED阶段并停止保活(见 mndProfile.c 中推送TXN_KILLEDkv 的逻辑)。也就是说,KILL TRANSACTION是管理员主动干预手段,而超时事务本身具备服务端自动终止并通知客户端的兜底机制。
重置客户端缓存:RESET QUERY CACHE
RESET QUERY CACHE;多客户端环境下若出现元数据不同步(例如各客户端本地缓存的库表元数据版本落后或不一致,导致查询行为与预期不符),可用本命令强制清空当前客户端的缓存;之后客户端会从服务端拉取最新元数据。
从源码结构看,该语句的节点类型为QUERY_NODE_RESET_QUERY_CACHE_STMT(parTranslater.c),与需要投递到 mnode 的 KILL 系列不同,它由客户端侧代码本地执行(涉及 clientImpl.c 与 command.c),即"重置的是当前执行该语句的客户端自身缓存",对其它客户端无副作用。因此当多个客户端同时出现元数据不同步时,需要在每个受影响客户端上分别执行。
推荐操作流程
结合上述机制,推荐的异常恢复操作顺序为:
- 定位:
SHOW CONNECTIONS/SHOW QUERIES/SHOW TRANSACTIONS(或直接查询PERF_CONNECTIONS、PERF_QUERIES、PERF_TRANS视图)拿到目标对象的conn_id、kill_id、trans_id,并核对user、end_point、pid、`sql`、killable等列确认归属与影响面; - 终止:按对象类型执行
KILL QUERY 'kill_id';(粒度最小,优先使用)、KILL CONNECTION conn_id;或KILL TRANSACTION trans_id;; - 验证:再次执行对应
SHOW语句确认对象已消失; - 元数据异常:若问题源于客户端缓存不一致,在对应客户端执行
RESET QUERY CACHE;后重试业务语句。
需要注意的适用前提:KILL 系列语句受操作权限约束(mnode 侧分别校验MND_OPER_KILL_CONN与MND_OPER_KILL_QUERY等权限,见 mndProfile.c),普通业务账号可能无权执行;且终止动作经心跳送达目标,存在一个心跳周期的延迟,属正常现象。
相关文档
- 异常恢复(官方原文档)
- SHOW 命令
- 性能数据视图(PERF_CONNECTIONS / PERF_QUERIES / PERF_TRANS)
- 元数据视图(INFORMATION_SCHEMA)
- mnode 连接/查询管理实现:mndProfile.c
- KILL 语句 parser 翻译:parTranslater.c
【免费下载链接】TDengineHigh-performance, scalable time-series database designed for Industrial IoT (IIoT) scenarios项目地址: https://gitcode.com/GitHub_Trending/tde/TDengine
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考