前言
某天凌晨,因为云侧故障发生ES重启,导致客户端通过线上SR查询ES外表时一直报索引找不到错误,具体报错信息如下:
ERROR 1064 (HY000): fetch es table [xxx] metadata failure: index[xxx] not found
当我们去通过原生es查询该索引时,发现索引是存在,因为正值大促期间,线上临时的解决方案是删掉表对表进行了重建,业务得到了恢复。
问题定位
代码定位该异常抛出位置为FE侧的EsRepository#runAfterCatalogReady

进入EsTable#syncTableMetaData方法,该方法看名字是同步表的元数据信息,内部实例化一个ES元数据状态的追踪器(EsMetaStateTracker), 通过EsMetaStateTracker#run方法启动
继续进入EsMetaStateTracker#run方法, 看起来是依次遍历并执行各个查询阶段
builtinSearchPhase接口: 有以下三种实现,分别用来获取ES的Mapping,Version, Partition;
继续进入MappingPhase#execute方法, 该方法通过getMapping获取json映射信息
继续进入EsRestClient#getMapping方法,该方法是构造请求Path, 然后调用execute方法具体执行,此处如果获取不到indexMapping, 会抛出异常, 此处注意有个includeTypeName决定了url的构建方式。
继续进入EsRestClient#execute方法,该方法就是具体执行http请求,返回Mapping信息。
通过使用athas工具跟踪,我们发现当线上ES为6.3.2版本时,includeTypeName值为true,这不符合业务代码中的逻辑,因为源代码中的逻辑只有大于7.X版本值该值才为true, 后续经过在测试环境安装指定版本的es进行重启并结合代码内部逻辑,定位到了变量值异常的原因:
ES某天凌晨宕机重启,在重启的过程中,client.version()获取版本的时候因为连不上es, 所以抛出了异常,异常被捕获之后,版本号被赋值为7.X, includeTypeName设置为true。当ES重启之后,版本号重新更新为了6.3.2,但是此时includeTypeName并没有重新被修改false。这个地方有一个corner case是:只有低版本变到高版本处理(见下图),当高版本降为低版本时,并没有去重新修改includeTypeName=false的操作。
最后
由于某些原因,通过athas定位线上问题的过程这里没有给出,主要涉及公司的一些敏感信息。在对线上问题进行修复之后,同社区进行了沟通并提交了我们修复的PR。目前该PR已经被合并,这个bug在SR2.4以下版本均存在,具体请参考:https://github.com/StarRocks/starrocks/pull/13995