首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > Mysql >

mysql存储过程执行追踪

2013-11-16 
mysql存储过程执行跟踪? ? ? ?学习mysql存储过程执行解析过程,执行一下存储过程? ? ? ?create procedure a

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 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; }

? ? ? ? ;

?

?

热点排行