YashanDB 知识库|insert 写入乱码字符,CPU 占满、线程卡死? 你可能踩到了 lex 死循环的坑
【问题现象】
在 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 中存在非法编码字符引起。示例中数据包含如下非法片段:
复制代码
这些字符既不是 GBK 编码,也不属于 UTF 编码范围。
服务端在解析 SQL 过程中进入:
复制代码
第一个非法字符(如 0x83)返回 mblen = -1
系统尝试后退 1 位继续识别(回到 '.'),再前进,又重新识别 0x83
于是形成 循环调用 → 无法退出 → 死循环
【复现路径】
由于普通 SQL 编写无法打出这些非法字符,测试人员通过 C 驱动+16 进制写入构造场景进行复现。

【风险说明】

【解决方案】
暂时恢复方法
复制代码
通过重启数据库集群,释放死循环线程,恢复系统状态。
长期解决建议
后续版本已修复 lex 处理非法编码导致死循环的 bug;
如使用旧版本,建议避免插入非法编码内容;
数据迁移前请统一字符集编码规范。
【预防建议】

【经验总结】
lex 层属于语法解析器的核心组件,一旦陷入循环会导致整个 SQL 处理栈无法退出;
编码错误是极易被忽视但影响深远的隐患;
数据处理工具链、接口数据源建议统一使用 UTF-8;
若必须使用 GBK,应明确字符支持范围,并在 ETL 前做字符合法性清洗。
评论