查看原文
其他

MySQL 8.0.23上遇到一个FIND_IN_SET的BUG

蓝树叶(成伟) 老叶茶馆 2024-07-08

本文为网友投稿。

作者:蓝树叶(成伟),运维工程师。

1、背景

在MySQL 8.0.23出现执行SQL超时的报错,而在MySQL8.0.18版本上未出现,故做个记录,以飨读者。

2、故障提要

在客户MySQL版本8.0.23,在部署客户测试环境时出现SQL执行超时报错。通过慢日志查询,找到对应的SQL。SQL如下:

SELECT * FROM t_dict WHERE FIND_IN_SET(id,(SELECT getDictChildrenNew(
        (select id from t_dict where code = 'metadata_classify'
     and root_code = 'metadata_classify' ),
        (select code from t_dict where code = 'metadata_classify'
     and root_code = 'metadata_classify' ),
        (select root_code from t_dict where code = 'metadata_classify'
     and root_code = 'metadata_classify' )
        )))
        order by dict_level,dict_order asc;

这个SQL用到了一个自定义函数getDictChildrenNew。函数内容如下:(真实的账号使用user_name代替了,已脱敏)

CREATE DEFINER=`user_name`@`%` FUNCTION `user_name`.`getDictChildrenNew`(iid varchar(255),icode varchar(255),ircode varchar(255)) RETURNS varchar(5000) CHARSET utf8mb4
    READS SQL DATA
BEGIN
DECLARE oTemp VARCHAR(5000);
DECLARE oTempChild VARCHAR(5000);
DECLARE oTempId VARCHAR(5000);
DECLARE oRootCode VARCHAR(5000);

SET oTemp = '';
SET oTempChild = icode;
SET oTempId = iid;
SET oRootCode = ircode;

WHILE oTempChild IS NOT NULL
DO
SET oTemp = CONCAT(oTemp,',',oTempId);

SELECT GROUP_CONCAT(ID) INTO oTempId
FROM t_dict
WHERE ROOT_CODE = oRootCode AND  FIND_IN_SET(PARENT_CODE,oTempChild);

SELECT GROUP_CONCAT(CODE) INTO oTempChild
FROM t_dict
WHERE ROOT_CODE = oRootCode AND FIND_IN_SET(PARENT_CODE,oTempChild);

END WHILE;
RETURN oTemp;
END

3、测试现象

我单独将where子句中这部分单独执行只需要122ms

SELECT getDictChildrenNew(
        (select id from t_dict where code = 'metadata_classify' #58
     and root_code = 'metadata_classify' ),
        (select code from t_dict where code = 'metadata_classify' #metadata_classify
     and root_code = 'metadata_classify' ),
        (select root_code from t_dict where code = 'metadata_classify' #metadata_classify
     and root_code = 'metadata_classify' )
        )

或者我单独将这个查询的值以字符串形式作为FIND_IN_SET的第二个参数传入执行也很快。仅需79ms。

而我单独执行上面完整的SQL就会出现超时报错:(这为了演示,我就没有等到报错再截图了)

奇怪的是这个SQL在MySQL8.0.18上没有出现问题。能快速正常的计算出结果(67ms):

4、总结

为此,我们目前给客户的建议是降低MySQL版本。

之所以给客户用8.0.18的旧版,是因为我们的产品在旧版上进行了很多轮次的测试都是正常的。而这一次客户现场测试环境的MySQL版本是客户定的,我们产品没在这个版本跑过,所以才给出这个建议的。后续我会在新版做一轮测试看看。

此外,我们也会尝试去MySQL官网报告bug(#105277)。


《实战MGR》视频课程

视频已全部上线,这是免费视频,放在腾讯课堂平台上,共有500多人报名学习了。

目前是第一期内容,相信有很多不足,甚至错漏的地方,也欢迎各位不吝留言帮忙提建议、意见,帮忙改进完善,感谢。

戳此小程序即可直达

或用微信/QQ扫码


或复制链接在浏览器中打开 GreatSQL社区《实战MGR》https://ke.qq.com/course/3677969



文章推荐:



扫码加入GreatSQL/MGR交流QQ群



点击文末“阅读原文”直达老叶专栏

继续滑动看下一个
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存