MySQL引擎分析-执行流程

MySQL存储引擎-执行流程

引言

本节通过分析show engines语句,理清sql语句的基本执行流程。关于MySQL协议
与网络处理这里略过,建议大家了解一下协议。对分析MySQL问题很有帮助,
有时利用tcpdump分析MySQL报文更高效。

SQL解析相关

这个条SQL语句虽简单,细究起来其实也颇为费解。这里首先说明一下SQL解析,
简单的说,SQL解析就是将SQL语句转换为一些的对象,这些对象构成语法分析树。
SQL解析是非常复杂繁琐的功能,需要将所有SQL语句匹配构成语法分析树,
其核心的两个工具yacc与lex。MySQL实现了lex词法分析模块,利用开源软件bison实现
语法分析模块,涉及的文件如下:

    /**************
    sql_lex.cc
    sql_lex.h
    sql_lex_hash.cc
    sql_lex_hash.h
    sql_lex_hints.cc
    sql_lex_hints.h
    sql_yacc.cc //自动生成的文件
    sql_yacc.h
    sql_yacc.yy
    ****************/

虽说只八个文件,但其复杂度却是指数级。但大家仍需要了解基本的yacc语法知识,
了解SQL语句解析过程,能够读懂sql_yacc.yy文件中内容。随后分析过程中,会涉
及sql_yacc.yy文件中内容。

函数调用

分析语句执行流程,函数流程如下:

    /*****************************************
    利用gdb调试工具,通过断点方式追踪,获得的堆栈信息。
    *****************************************/
    handle_connection();
    //connection_handler_per_thread.cc
    /*  对于每个Client,MySQL另起一个Pthread线程,
        运行此函数处理连接直至断开。
        其中for与while双重循环,挺nice的设计
    */

    do_command();               //sql_parse.cc
    /*  阻塞等待读取网络输入,就是客户发送的请求报文。
        分析报文类型,涉及MySQL协议,需大家了解一下MySQL协议。
        协议规定了报文,前4个字节格式固定,随后为数据内容。
        其中前3个字节,数据内容长度,第四个字节报文序号。
        数据内容的第一个字节为报文类型。
    */

     dispatch_command();         //sql_parse.cc
    /*  根据报文类型,做第一次分发处理。
        show engines属于COM_QUERY报文类型。
    */

    mysql_parse();              //sql_parse.cc
    /*  确实是否缓存了query结果,若存在则直接响应。
        调用parse_sql解析sql,构造查询语法分析树,匹配sql_yacc.yy文件11709行。
        将show engines语句转换为对INFORMATION_SCHEMA.ENGINES的SELECT操作。
        prepare_schema_table
            make_schema_select
            make_old_format
            add_table_to_list
    */

    mysql_execute_command();
    /*根据SQL类型,做二次分发, SELECT类型*/

    execute_sqlcom_select();        //sql_select.cc
        open_tables_for_query()     //sql_base.cc
        open_tables();              //sql_base.cc
        open_and_process_table();   //sql_base.cc
        mysql_schema_table();       //sql_show.cc
        create_schema_table();      //sql_show.cc
        create_tmp_table();         //sql_tmp_file.cc
    /*  Open所有将操作的表,INFORMATION_SCHEMA是虚拟的数据库,
        其中的表是虚拟表,需要构造表的Schema。
        创建其ENGINES表memory引擎对应的handler对象,将其赋给Table对象的file属性。
        【Table与handler关联起来】
    */

    handle_query();             //sql_select.cc
        prepare();
        optimize();
    /*  处理了SQL的优化操作,后续分析SQL优化处理*/


    JOIN::exec();               //sql_executor.cc
        JOIN::prepare_result()      //sql_select.cc
            get_schema_tables_result(); //sql_show.cc
            do_fill_table();            //sql_show.cc
            fill_schema_engines();      //sql_show.cc
            plugin_foreach_with_mask(); //sql_plugin.cc
            iter_schema_engines();      //sql_show.cc
            schema_table_store_record();    //sql_show.cc
            table->file->ha_write_row();
    /*  全局plugin_hash中类型为存储引擎的插件,进行遍历操作,
        将数据构建为ENGINES表的记录。并将其存入memory引擎的ENGINES表中。
    */

    send_result_set_metadata();
    //ENGINES表SCHEMA信息发送至Client

    /*Server最复杂核心逻辑之一,后续分析SELECT操作*/
    do_select();

    //回退到dispatch_command,并执行如下语句后,至此执行完成。
    //client显示数据集
    send_statement_status();
        Protocol_classic::send_eof();
        net_send_ok();
        net_flush();
        net_write_packet();
        query_cache_insert();

总结

这里只分析了主干流程,细节都未完成剖析,走马观花而已。通过流程分析,
可看出简单的show engines语句的执行,并不是想象中的那么简单。
上篇分析了Engine插件的初始化操作,现已了解Engine如何与Table建立关联。
接下来介绍如何将leveldb作为存储引擎集成到MySQL中。

展开阅读全文

没有更多推荐了,返回首页