设为首页 收藏本站
查看: 553|回复: 0

[经验分享] mysql存储过程执行跟踪

[复制链接]

尚未签到

发表于 2016-9-20 10:55:28 | 显示全部楼层 |阅读模式
  学习mysql存储过程执行解析过程,执行一下存储过程
  create procedure aa()
  begin
  declare x varchar(10);
  select count(*) from test where aaa = x ;
  end
  在JOIN::exec上设个断点,跟踪一下
  执行堆栈如下:
  #0  JOIN::exec (this=0x900e548) at sql_select.cc:2311
  #1  0x08268373 in mysql_select (thd=0xb53d2fd0, rref_pointer_array=0x9005984, tables=0x9006040, wild_num=0, fields=@0x9005914, conds=0x90065f8, og_num=0, order=0x0, group=0x0, having=0x0, proc_param=0x0, select_options=2147765760, result=0x900c698, unit=0x90055ec, select_lex=0x9005880) at sql_select.cc:3067
  #2  0x0826887d in handle_select (thd=0xb53d2fd0, lex=0x9005590, result=0x900c698, setup_tables_done_option=0) at sql_select.cc:310
  #3  0x081e1af7 in execute_sqlcom_select (thd=0xb53d2fd0, all_tables=0x9006040) at sql_parse.cc:4943
  #4  0x081e432f in mysql_execute_command (thd=0xb53d2fd0) at sql_parse.cc:2157
  #5  0x0835c987 in sp_instr_stmt::exec_core (this=0x90066f0, thd=0xb53d2fd0, nextp=0xb54912d0) at sp_head.cc:2927
  #6  0x0835cbd1 in sp_lex_keeper::reset_lex_and_exec_core (this=0x9006718, thd=0xb53d2fd0, nextp=0xb54912d0, open_tables=false, instr=0x90066f0) at sp_head.cc:2751
  #7  0x08363962 in sp_instr_stmt::execute (this=0x90066f0, thd=0xb53d2fd0, nextp=0xb54912d0) at sp_head.cc:2864
  #8  0x08360f89 in sp_head::execute (this=0x9004560, thd=0xb53d2fd0) at sp_head.cc:1248
  #9  0x08361a53 in sp_head::execute_procedure (this=0x9004560, thd=0xb53d2fd0, args=0xb53d44bc) at sp_head.cc:1989
  #10 0x081e966a in mysql_execute_command (thd=0xb53d2fd0) at sql_parse.cc:4401
  #11 0x081ebbfa in mysql_parse (thd=0xb53d2fd0, inBuf=0x8fdfa58 "call aa()", length=9, found_semicolon=0xb5491f14) at sql_parse.cc:5958
  #12 0x081ecae6 in dispatch_command (command=COM_QUERY, thd=0xb53d2fd0, packet=0xb53f35c9 "call aa()", packet_length=9) at sql_parse.cc:1049
  #13 0x081eddaa in do_command (thd=0xb53d2fd0) at sql_parse.cc:731
  #14 0x081dd5a7 in handle_one_connection (arg=0xb53d2fd0) at sql_connect.cc:1146
  #15 0x4dfe92db in start_thread (arg=0xb5492790) at pthread_create.c:296
  #16 0x006cf14e in clone () from /lib/libc.so.
  具体代码
  在sql_parse.cc中
  case SQLCOM_CALL:
  ....
  sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname,
  &thd->sp_proc_cache, TRUE)) -------此处对存储过程进行解析
  ....
  res= sp->execute_procedure(thd, &lex->value_list); -------执行存储过程
  }
  
  bool sp_head::execute_procedure(THD *thd, List<Item> *args){
  ....
  //前面对参数进行一些处理
  if (!err_status)
  err_status= execute(thd);//具体执行存储过程
  ...对出参进行处理
  }
  
  bool   sp_head::execute(THD *thd){
  ...
  
  do
  {
  sp_instr *i;
  uint hip;
  i = get_instr(ip);// Returns NULL when we're done.
  err_status= i->execute(thd, &ip); //执行存储过程中的每一个语句,每个具体语句都解析为sp_instr的子类
  }while (!err_status && !thd->killed && !thd->is_fatal_error);
  //上面循环其实就是一个sql的执行引擎,不断读入执行,直到结束
  }
  
  int sp_instr_stmt::exec_core(THD *thd, uint *nextp)
  {
  MYSQL_QUERY_EXEC_START(thd->query,
  thd->thread_id,
  (char *) (thd->db ? thd->db: ""),
  thd->security_ctx->priv_user,
  (char *) thd->security_ctx->host_or_ip,
  3);
  int res= mysql_execute_command(thd); //对每一个sql进行执行。这里就和普通的sql是一样了
  MYSQL_QUERY_EXEC_DONE(res);
  *nextp= m_ip+1; //将上面ip推进到下一条语句,让上面的循环执行下一个语句
  return res;
  }
  
  看一下解析器解析的中where 
  
  where aaa = x 
  |
  |--> where Item_func_eq  -----表示这是个等于条件操作
  |                                  / Item_field ----代表字段aaa
  |-----> Item** args -----|
  \ Item_sp_local--代表变量x
  解析在sql_yacc.yy中
  simple_ident:
  ident
  {
  THD *thd= YYTHD;
  LEX *lex= thd->lex;
  Lex_input_stream *lip= YYLIP;
  sp_variable_t *spv;
  sp_pcontext *spc = lex->spcont;
  if (spc && (spv = spc->find_variable(&$1))) //判断语句中是否有变量
  {
  /* We're compiling a stored procedure and found a variable */
  if (! lex->parsing_options.allows_variable)
  {
  my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
  MYSQL_YYABORT;
  }
  
  Item_splocal *splocal;
  splocal= new (thd->mem_root)
  Item_splocal($1,
  spv->offset, spv->type,
  lip->get_tok_start_prev() - lex->sphead->m_tmp_query,
  lip->get_tok_end() - lip->get_tok_start_prev());
  if (splocal == NULL)
  MYSQL_YYABORT;
  #ifndef DBUG_OFF
  splocal->m_sp= lex->sphead;
  #endif
  $$= splocal;
  lex->safe_to_cache_query=0;
  }
  else
  {
  SELECT_LEX *sel= Select;
  if ((sel->parsing_place != IN_HAVING) ||
  (sel->get_in_sum_expr() > 0))
  {
  $$= new (thd->mem_root) Item_field(Lex->current_context(),
  NullS, NullS, $1.str);
  }
  else
  {
  $$= new (thd->mem_root) Item_ref(Lex->current_context(),
  NullS, NullS, $1.str);
  }
  if ($$ == NULL)
  MYSQL_YYABORT;
  }
  }
  | simple_ident_q { $$= $1; }
  ;
  
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-274902-1-1.html 上篇帖子: mysql 常用小操作 下篇帖子: mysql 表结构损坏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表