首页 > 数据库 >GreatSQL的sp中添加新的sp_instr引入的bug解析

GreatSQL的sp中添加新的sp_instr引入的bug解析

时间:2024-05-08 09:44:24浏览次数:27  
标签:instr sp GreatSQL 添加 statement sql class

GreatSQL的sp中添加新的sp_instr引入的bug解析

一、问题发现

在一次开发中用到的sp需要添加新的sp_instr以满足需求,但是添加了数个sp_instr以后发现执行新的sp会发生core。

注:本次使用的GreatSQL 8.0.32-25

1、sp_head.cc的init_sp_psi_keys()代码里面添加10个新的sp_instr:

void init_sp_psi_keys() {
  mysql_statement_register(category, &sp_instr_stmt1::psi_info, 1);
  mysql_statement_register(category, &sp_instr_stmt2::psi_info, 1);
  mysql_statement_register(category, &sp_instr_stmt3::psi_info, 1);
  ......
  mysql_statement_register(category, &sp_instr_stmt10::psi_info, 1);
}

2、sp_instr.cc里面添加新的sp_instr_stmt相关实现代码,其中sql_yacc.yy和sql_lex.cc需要相应添加新的语法。

3、sp_rcontext.h处在·class sp_rcontext里面添加几个新的成员变量。下面代码只是示例,不具有实际使用价值。

  Field *m_return_value_fld_tmp{m_return_value_fld};
  Field *m_return_value_fld_tmp1{m_return_value_fld};
  Field *m_return_value_fld_tmp2{m_return_value_fld};

4、创建新的sp,里面包含新的sp_instr_stmt的内容,然后call该sp,结果发现代码逻辑处因为一个list里面member的值被清空了,然后导致crash。下面是相关的堆栈。因为涉及代码机密,只截图开源部分相关堆栈。

#0  0x0000555558f3f3d9 in base_list_iterator::next_fast (this=0x7fffe01e9de0)
    at /sql/sql_list.h:371
#1  0x0000555558fc59b7 in List_iterator_fast<Create_field>::operator++ (this=0x7fffe01e9de0)
    at /sql/sql_list.h:605
#2  0x0000555559753ea2 in create_tmp_table_from_fields (thd=0x7fff20001050, field_list=..., 
    is_virtual=false, select_options=0, alias=0x0)
    at /sql/sql_tmp_table.cc:2131
#3  0x0000555559084a09 in Item_xx::val_str (this=0x7fff20b673c8)
    at /sql/item_func.cc:10796
#4  0x0000555558fa408b in Item::save_in_field_inner (this=0x7fff20b673c8, field=0x7fff20b9b1a8, 
    no_conversions=false) at /sql/item.cc:8202
#5  0x0000555558fa3c43 in Item::save_in_field (this=0x7fff20b673c8, field=0x7fff20b9b1a8, 
    no_conversions=false) at /sql/item.cc:8144
#6  0x0000555559400322 in sp_eval_expr (thd=0x7fff20001050, result_field=0x7fff20b9b1a8, 
    expr_item_ptr=0x7fff20b67620) at /sql/sp.cc:3613
#7  0x000055555943b1d1 in sp_rcontext::set_variable (this=0x7fff20b85d80, thd=0x7fff20001050, 
    field=0x7fff20b9b1a8, value=0x7fff20b67620)
    at /sql/sp_rcontext.cc:1023
#8  0x0000555558fc3a8e in sp_rcontext::set_variable (this=0x7fff20b85d80, thd=0x7fff20001050, 
    var_idx=1, value=0x7fff20b67620)
    at /sql/sp_rcontext.h:176
打印crash处的信息,发现list里面的值被清空了。
(gdb) p tmp
$1 = (list_node *) 0x0

二、问题调查过程

1、仔细检查代码发现代码逻辑没有问题,list的值确实都有成功赋值,但是运行时候却发现list被清空,显然这是别的地方内存泄漏或者内存溢出导致list的元素空间被占用了或者被清空了。把sp的代码换成别的,有时候会crash有时候不会crash,触发机制也不明朗,不知道具体哪句代码导致的内存泄漏。

2、于是回头继续看刚开始添加代码的地方,猜想是不是跟我添加了10个sp_instr_stmt有关,因为相关的数组或者内存没有添加扩容,很有可能因为这个导致内存溢出。

3、定位出疑似问题地方,就可以着手开始调查相关代码了。查看相关添加sp_instr的代码。

添加sp_instr实现代码如下:
mysql_statement_register(category, &sp_instr_stmt1::psi_info, 1);

于是继续往下面调查mysql_statement_register实现的代码,看到这里果然用到了statement_class_max:
PFS_statement_key register_statement_class(const char *name, uint name_length,
                                           PSI_statement_info *info) {
  /* See comments in register_mutex_class */
  uint32 index;
  PFS_statement_class *entry;

  REGISTER_CLASS_BODY_PART(index, statement_class_array, statement_class_max,
                           name, name_length)

接着查看statement_class_max的赋值的地方:
int init_statement_class(uint statement_class_sizing) {
  int result = 0;
  statement_class_dirty_count = statement_class_allocated_count = 0;
  statement_class_max = statement_class_sizing;

通过搜索代码查到statement_class_sizing相关的参数配置的地方,看到这里有一个SP_PSI_STATEMENT_INFO_COUNT宏定义,这个值跟sp_instr的数量有关。
static Sys_var_ulong Sys_pfs_max_statement_classes(
    "performance_schema_max_statement_classes",
    "Maximum number of statement instruments.",
    READ_ONLY GLOBAL_VAR(pfs_param.m_statement_class_sizing),
    CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 256),
    DEFAULT((ulong)SQLCOM_END + (ulong)COM_END + 5 +
            SP_PSI_STATEMENT_INFO_COUNT + CLONE_PSI_STATEMENT_COUNT),
    BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);

继续全文搜索,发现在sp_head.h定义了,这里的值为16,数了一下现存的sp_instr个数刚好为16个,至此问题原因发现,因为我加了10个sp_instr,而这个宏定义的值没有跟着增加,导致内存溢出。
#define SP_PSI_STATEMENT_INFO_COUNT 16

三、问题解决方案

通过以上代码解析后,就可以修改相关问题代码,只要作如下修改即可。重新编译完,问题解决。

sp_head.h修改SP_PSI_STATEMENT_INFO_COUNT宏定义:
#define SP_PSI_STATEMENT_INFO_COUNT 26

因为增加了Sys_pfs_max_statement_classes的default值,因为相关配置范围也要跟着增加,因此把range相应加大。
static Sys_var_ulong Sys_pfs_max_statement_classes(
    "performance_schema_max_statement_classes",
    "Maximum number of statement instruments.",
    READ_ONLY GLOBAL_VAR(pfs_param.m_statement_class_sizing),
    CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 256 * 2),
    DEFAULT((ulong)SQLCOM_END + (ulong)COM_END + 5 +
            SP_PSI_STATEMENT_INFO_COUNT + CLONE_PSI_STATEMENT_COUNT),
    BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);

四、问题总结

在GreatSQL的sp添加新的sp_instr需要相应增加对应的参数值以防止内存溢出,如果其他的功能也要做类似的修改,也要先仔细调查一下有没有涉及相关的参数配置或者宏定义,不然就会遇到各种莫名其妙的问题,调查起来也很花时间。

这次发现的问题属于新添加功能带入的bug,在实际开发应用中类似的问题也要注意,一不小心就会踩坑。

上述问题在MySQL/Percona中同样存在。


Enjoy GreatSQL

标签:instr,sp,GreatSQL,添加,statement,sql,class
From: https://www.cnblogs.com/greatsql/p/18178998

相关文章

  • 谈springboot两种实现结构
    概述最近由于入职华海智汇,所以文章也少了,并不是自己懈怠了,而是华海的保密措施不允许我上班写文章了,更何况还有无尽的加班。。。。。。。。。唉,所幸现在习惯了好多,现在觉着该记录一下知识了。目前市场上,要实现Java项目主要有Maven和Gradle两种框架,其中Gradle是新兴势力,Maven是老牌......
  • 27-Spring源码分析(二)
    AOP源码分析1.AOP概述AOP(AspectOrientProgramming)利用代理模式,通过代理对象对被代理的对象增加功能。所以,关键在于AOP框架自动创建AOP代理对象,代理模式分为静态代理和动态代理。AspectJ使用静态代理,编译时增强,在编译期生成代理对象;SpringAOP使用动态代理,运行时......
  • Spring SpringMVC概述
    SpringMVC框架主要用于跟客户端交互,包括请求和响应。  前端控制器的作用就是把一些功能封装,我们在开发时就不用再写一些繁杂的代码了SpringMVC使用DispatcherServlet作为前端控制器,DispatcherServlet本质其实是一个Servlet 原先我们在访问时,客户端发起请求直接找Servlet......
  • k8s常见安装方式 rancher kubespray kops kubeadm对比
    Kubernetes(K8s)的常见安装方式包括Rancher、Kubespray、kops和kubeadm,它们各自具有不同的特点和适用场景。以下是这四种安装方式的对比:Rancher:Rancher是一个开源的企业级Kubernetes管理平台,它简化了Kubernetes的部署、扩展和管理。通过Rancher,用户可以轻松地在各种基础设施上部......
  • [转]openEuler 22.03 (LTS-SP1)安装最新版Docker(踩坑及解决方案)
    原文地址:openEuler22.03(LTS-SP1)安装最新版Docker(踩坑及解决方案)_openeulerdocker-CSDN博客openEuler22.03LTS-SP1要是直接yuminstalldocker,默认安装docker是18.09.0,这个版本Docker有个bug,所以还是安装个最新版Docker。1、先增加docker官方仓库[[email protected]......
  • SpringBoot+Thymeleaf渲染下拉框异常解决
    常规方式<selectclass="form-control"name="operationType"th:field="${itemTemp.operationType}"style="width:80%"th:disabled="${readonly}"><optionvalue="">选......
  • Springboot+Netty实现http和ws统一端口处理
    http:/localhost:8080/apiws:/localhost:8080/ws核心就是两个channel处理器,http和wswebsocketpackagecom.example.netty;importio.netty.channel.ChannelHandlerContext;importio.netty.channel.SimpleChannelInboundHandler;importio.netty.handler.codec.http.HttpH......
  • Appium Inspector与Weditor:移动端测试的利器
    简介元素定位工具是在软件开发和自动化测试中精确定位和操作用户界面元素的工具。元素定位工具可以提供辅助定位元素、编写代码、录制用例、调试代码等功能。在移动端应用的自动化测试中,一款灵活的元素定位工具是必不可缺的,本节推荐两种定位工具,分别为官网提供的AppiumInspetor......
  • mybatisplus批量插入,分批的功能
    默认分批是1000一般也就改成100-1000之间示业务而定 比较简洁的一种方式如下原代码publicBooleaninsertTasks(List<TaskInfoEntity>tasks,StringagentId){//todo分批List<AgentTaskRelationEntity>entities=tasks.stream().map((......
  • SpringBoot集成WebSocket
    SpringBoot集成WebSocket1.引jar包<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><dependency&......