
MySQL的match函数在sp中使用的BUG解析
- 一、问题发现
- 二、问题调查过程
- 三、问题解决方案
- 四、问题总结
一、问题发现
在一次开发中在sp中使用MySQL PREPARE
以后,使用match AGAINST
语句作为prepare stmt
的参数后,发现执行第二遍call会导致数据库crash,于是开始动手调查问题发生的原因。
注:本次使用的 MySQL 数据库版本为最新的debug版本。
SQL语句示例:
二、问题调查过程
1、首先查看错误堆栈信息,可以看到Item_func_match::val_real
函数的item->real_item()->type()
不等于FIELD_ITEM
引起的,打印堆栈看了一下,此时的item->real_item()为Item_splocal
,明显不是FIELD_ITEM
。
2、要想获取sp参数的实际item,应该调用this_item()
方法,但是也许作者本来就不想让match
支持sp参数,因此这里的写法是对的。但是本来代码不应该运行到这里,因为本来应该直接报错。
3、接着继续调查,查看第一次报错的地方的代码,找到Item_func_match::fix_fields
,看到了第一次报错的地方的代码item->type() != Item::FIELD_ITEM
,因此代码运行应该在这里报错。但是为何第二次执行会运行到Item_func_match::val_real
而不是在Item_func_match::fix_fields
就直接报错返回呢?仔细查看下面的代码,发现下面的代码有1个地方有错误。
三、问题解决方案
通过以上代码解析后作如下修改,正确给fixed
赋值,这样就可以保证每次call sp
的时候如果遇到报错再次运行还会重新执行fix_fields
。
现在重新执行call sp,没有问题了。
四、问题总结
本次只是解决了match
的fix_fields
问题,但是如果想让 match
支持 sp 的参数,即Item_splocal
的参数的话,代码里面还要做相应修改,包括set @bb := match(a,b) AGAINST ('collections');
这里面生成的Item_func_match
会在这句执行完以后被 cleanup 掉,等到下一句 prepare 想再次使用它的时候会因为找不到该item发生问题,这个是重构 match函数
支持 sp 参数需要注意的点。
Enjoy GreatSQL :)
文章转载自公众号:GreatSQL社区
