mysql存储过程运⾏跟踪_mysql存储过程执⾏跟踪
学习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 :2311
#1  0x08268373 in mysql_select (thd=0xb53d2fd0, rref_pointer_array=0x9005984, tables=0x9006040, wi
ld_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 :3067
#2  0x0826887d in handle_select (thd=0xb53d2fd0, lex=0x9005590, result=0x900c698, setup_tables_done_option=0) at :310
#3  0x081e1af7 in execute_sqlcom_select (thd=0xb53d2fd0, all_tables=0x9006040) at :4943
#4  0x081e432f in mysql_execute_command (thd=0xb53d2fd0) at :2157
#5  0x0835c987 in sp_instr_stmt::exec_core (this=0x90066f0, thd=0xb53d2fd0, nextp=0xb54912d0) at
:2927
#6  0x0835cbd1 in sp_lex_keeper::reset_lex_and_exec_core (this=0x9006718, thd=0xb53d2fd0, nextp=0xb54912d0, open_tables=false, instr=0x90066f0) at :2751
#7  0x08363962 in sp_instr_stmt::execute (this=0x90066f0, thd=0xb53d2fd0, nextp=0xb54912d0) at :2864
#8  0x08360f89 in sp_head::execute (this=0x9004560, thd=0xb53d2fd0) at :1248
#9  0x08361a53 in sp_head::execute_procedure (this=0x9004560, thd=0xb53d2fd0, args=0xb53d44bc) at
:1989
#10 0x081e966a in mysql_execute_command (thd=0xb53d2fd0) at :4401
#11 0x081ebbfa in mysql_parse (thd=0xb53d2fd0, inBuf=0x8fdfa58 "call aa()", length=9, found_semicolon=0xb5491f14) at :5958
#12 0x081ecae6 in dispatch_command (command=COM_QUERY, thd=0xb53d2fd0, packet=0xb53f35c9 "call aa()",
packet_length=9) at :1049
#13 0x081eddaa in do_command (thd=0xb53d2fd0) at :731
#14 0x081dd5a7 in handle_one_connection (arg=0xb53d2fd0) at :1146
#15 0x4dfe92db in start_thread (arg=0xb5492790) at pthread_create.c:296
#16 0x006cf14e in clone () from /lib/libc.so.
具体代码
在中
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 *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
解析在中
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
mysql存储过程使用
{
$$= new (thd->mem_root) Item_ref(Lex->current_context(), NullS, NullS, $1.str);
}
if ($$ == NULL)
MYSQL_YYABORT;
}
}
| simple_ident_q { $$= $1; }
;

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。