写点什么

YashanDB 知识库|insert 写入乱码字符,CPU 占满、线程卡死? 你可能踩到了 lex 死循环的坑

作者:数据库砖家
  • 2025-05-12
    广东
  • 本文字数:637 字

    阅读完需:约 2 分钟

【问题现象】

在 GBK 编码的 YashanDB 数据库中,执行某条 insert 语句后:

SQL 长时间无响应

CPU 资源占满(单核 99.9%)

kill session 后也无法释放

查看线程状态,发现 yasdb worker 长时间占用 CPU,而会话处于 killed 状态却无法销毁。


【影响版本】

YashanDB 22.2.16.1

YashanDB 23.3.0.61 及更早版本

【根因分析】

✳ 问题本质:编码非法字符导致 lex 模块陷入死循环

分析表明,该问题由 SQL 中存在非法编码字符引起。示例中数据包含如下非法片段:

0x83. 0x36. 0xCA, 0x33
复制代码

这些字符既不是 GBK 编码,也不属于 UTF 编码范围。

服务端在解析 SQL 过程中进入:

lex → gbkNextCharLengthb
复制代码

第一个非法字符(如 0x83)返回 mblen = -1

系统尝试后退 1 位继续识别(回到 '.'),再前进,又重新识别 0x83

于是形成 循环调用 → 无法退出 → 死循环

【复现路径】

由于普通 SQL 编写无法打出这些非法字符,测试人员通过 C 驱动+16 进制写入构造场景进行复现。

【风险说明】

【解决方案】

暂时恢复方法

yasboot cluster restart -c yashandb -d
复制代码

通过重启数据库集群,释放死循环线程,恢复系统状态。

长期解决建议

后续版本已修复 lex 处理非法编码导致死循环的 bug;

如使用旧版本,建议避免插入非法编码内容;

数据迁移前请统一字符集编码规范。

【预防建议】

【经验总结】

lex 层属于语法解析器的核心组件,一旦陷入循环会导致整个 SQL 处理栈无法退出;

编码错误是极易被忽视但影响深远的隐患;

数据处理工具链、接口数据源建议统一使用 UTF-8;

若必须使用 GBK,应明确字符支持范围,并在 ETL 前做字符合法性清洗。

用户头像

还未添加个人签名 2025-04-09 加入

还未添加个人简介

评论

发布
暂无评论
YashanDB 知识库|insert 写入乱码字符,CPU 占满、线程卡死?你可能踩到了 lex 死循环的坑_数据库_数据库砖家_InfoQ写作社区