• MYSQL的启动


    MYSQL的启动

    主程序是在mysqld.cc这个文件,入口是win_main,或者是mysqld_main()这个函数

     初始化,包括pthreads线程和系统库。在line #4359附近的地方。

    if (my_init()) // init my_sys library & pthreads

      {

        sql_print_error("my_init() failed.");

        flush_error_log_messages();

        return 1;

      }

    第二步,读配置文件

    if (load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv))

      {

        flush_error_log_messages();

        return 1;

      }

    第三步:登记Performance Schema

     第四步:初始化init_error_log() 和 query_logger.init()

    定位data_dir目录,即数据文件路径。

    如果启用了binlog,则必须提供server-id

     初始化init_SSL()和初始化网络 network_init()

     产生一个PID文件。

    =========

    每个线程处理命令的函数为:

    bool do_command(THD *thd) 

    {

    //从网络协议中,获得待执行的命令

    rc= thd->get_protocol()->get_command(&com_data, &command);

           //派遣命令

           return_value= dispatch_command(thd, &com_data, command);

     }

      

    bool dispatch_command(THD *thd, const COM_DATA *com_data,

                          enum enum_server_command command)

    {

    //开始执行命令

      /* DTRACE instrumentation, begin */

      MYSQL_COMMAND_START(thd->thread_id(), command,

                          (char *) thd->security_context()->priv_user().str,

                          (char *) thd->security_context()->host_or_ip().str);

    }

    如何排查一个查询语句的表:

    0:006> dv

                thd = 0x00000000`0e2c4b90

       parser_state = 0x00000000`0e2c4b90

    0:006> dt thd

    Local var @ 0xf80ec60 Type THD*

    0x00000000`0e2c4b90

       +0x000 __VFN_table : 0x00000001`40a507b8

       +0x008 __VFN_table : 0x00000001`40a50810

       +0x010 free_list        : 0x00000000`0dfd0e08 Item

       +0x018 mem_root         : 0x00000000`0e2c7268 st_mem_root

       +0x020 state            : 3 ( STMT_CONVENTIONAL_EXECUTION )

       +0x028 m_reprepare_observers : Prealloced_array<Reprepare_observer *,4,1>

       +0x068 open_tables      : (null)

       +0x070 temporary_tables : (null)

       +0x078 derived_tables   : (null)

       +0x080 lock             : (null)

       +0x088 extra_lock       : (null)

       +0x090 locked_tables_mode : 0 ( LTM_NONE )

       +0x094 state_flags      : 0

       +0x098 mdl_context      : MDL_context

       +0x180 mark_used_columns : 1 ( MARK_COLUMNS_READ )

       +0x184 want_privilege   : 0xbfffffff

       +0x188 lex              : 0x00000000`0e2c6888 LEX

      

      

    0:006> dt 0x00000000`0e2c6888 LEX

    mysqld!LEX

       +0x008 sql_command      : 0 ( SQLCOM_SELECT )

       +0x010 query_tables     : 0x00000000`0dfd11c0 TABLE_LIST

    0:006> dt 0x00000000`0dfd11c0 TABLE_LIST

    mysqld!TABLE_LIST

       +0x000 next_local       : (null)

       +0x008 next_global      : (null)

       +0x010 prev_global      : 0x00000000`0e2c6898  -> 0x00000000`0dfd11c0 TABLE_LIST

       +0x018 db               : 0x00000000`0dfd1738  "sakila"

       +0x020 table_name       : 0x00000000`0dfd0930  "country"

       +0x028 alias            : 0x00000000`0dfd11b8  "country"

       +0x030 target_tablespace_name : st_mysql_const_lex_string

       +0x040 schema_table_name : (null)

       +0x048 option           : (null)

     

    thd有一个成员变量:是用于存放查询字符串的。

       +0x198 m_query_string   : st_mysql_const_lex_string

    查询方式如下:在MYSQL_PARSE()的地方,稍微往下走几步。否则显示不出来。

    0:006> dv

                thd = 0x00000000`0e2c4b90

       parser_state = 0x00000000`0e2c4b90

    0:006> dt thd+0x198 st_mysql_const_lex_string

    mysqld!st_mysql_const_lex_string

       +0x000 str              : 0x00000000`0dfcfc18  ""

       +0x008 length           : 0xdfcfbd0

    0:006> db 0x00000000`0dfcfc18

    00000000`0dfcfc18  00 fe fc 0d 00 00 00 00-73 65 6c 65 63 74 20 63  ........select c

    00000000`0dfcfc28  6f 75 6e 74 72 79 5f 69-64 2c 20 63 6f 75 6e 74  ountry_id, count

    00000000`0dfcfc38  72 79 20 66 72 6f 6d 20-63 6f 75 6e 74 72 79 20  ry from country

    00000000`0dfcfc48  77 68 65 72 65 20 63 6f-75 6e 74 72 79 20 6c 69  where country li

    00000000`0dfcfc58  6b 65 20 27 61 6e 25 27-20 6c 69 6d 69 74 20 35  ke 'an%' limit 5

    00000000`0dfcfc68  00 00 00 00 00 00 00 00-c0 64 a5 40 01 00 00 00  .........d.@....

    00000000`0dfcfc78  00 00 00 00 00 00 00 00-68 ff fc 0d 00 00 00 00  ........h.......

    00000000`0dfcfc88  50 ff fc 0d 00 00 00 00-00 00 00 00 00 00 00 00  P...............

      

    数据库记录中的页(Page)信息。

    这个记录是逻辑页:

    0:006> dt dtuple_t

    mysqld!dtuple_t

       +0x000 info_bits        : Uint8B

       +0x008 n_fields         : Uint8B

       +0x010 n_fields_cmp     : Uint8B

       +0x018 fields           : Ptr64 dfield_t

       +0x020 n_v_fields       : Uint8B

       +0x028 v_fields         : Ptr64 dfield_t

       +0x030 tuple_list       : ut_list_node<dtuple_t>

     

     

     

    /********************************************************************//**

    Positions a cursor on the first record in an index and reads the corresponding row to buf.

    @return 0, HA_ERR_END_OF_FILE, or error code */

     

    int

    ha_innobase::index_first(

          uchar*      buf)  /*!< in/out: buffer for the row */

    {

          DBUG_ENTER("index_first");

          ha_statistic_increment(&SSV::ha_read_first_count);

          int   error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);

          /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */

          if (error == HA_ERR_KEY_NOT_FOUND) {

                error = HA_ERR_END_OF_FILE;

          }

          DBUG_RETURN(error);

    }

    MySQL的SELECT语句执行在innobase ow ow0sel.cc这个文件中。

    Do_select(); 查询入口函数

    | Sub_SELECT(); 查询部分JOIN的记录。循环调用ha_innobase::rnd_next()和evaluate_join_record() 获取并处理该部分的每条记录。

    || evaluate_join_record(): 处理一条查询记录。

    || rr_sequential(); 调用ha_innobase::rnd_next()读取下一条记录。

    ||| ha_innobase::rnd_next(): 读取下一条记录。

    |||| ha_innobase::general_fetch(); 从给定的索引位置获取下一条或上一条记录

    ||||| row_search_for_mysql():从数据库中查询一条记录。以下分为六个阶段分别处理各个部分。

    |||||| 第一阶段: 释放自适应hash索引的锁

    ||||||| rw_lock_get_writer() 函数用于获取读写锁,如果获取失败,释放目前的读写锁

    |||||| 第二阶段:从预读的cache中获取记录

    ||||||| row_sel_pop_cached_row_for_mysql(); 函数用于从cache中读取一行记录。

    |||||||| row_sel_copy_cached_field_for_mysql(); 函数读取每个字段。

    |||||| 第三阶段:使用自适应hash索引快速查找

    ||||||| row_sel_try_search_shortcut_for_mysql() 函数使用hash索引获取聚集索引的记录

    |||||||| row_sel_store_mysql_rec() 函数将获取的innobase格式行记录转化为mysql格式

    ||||||||| row_sel_field_store_in_mysql_format() 函数将innobase格式的行记录中的每个字段转化为mysql格式

    |||||| 第四阶段:打开并恢复索引的游标位置

    ||||||| sel_restore_position_for_mysql(); 恢复索引的游标位置

    |||||||| btr_pcur_restore_position_func(): 恢复一个持久化游标的位置

    ||||||||| btr_cur_get_index(); 获取索引

    ||||||||| buf_page_optimistic_get()

    ||||||||| btr_pcur_get_rec() 获取持久化游标的记录

    |||||||||| btr_cur_get_rec(); 获取当前游标位置的记录

    ||||||||| rec_get_offsets_func(): 获取记录中每个字段的偏移

    |||||||| btr_pcur_move_to_next(); 移动持久化游标到下一条记录

    |||||| 第五阶段:查找匹配的记录

    ||||||| page_rec_is_infimum(): 查看当前记录是否是该页的infinum记录。Infinum记录表示比任何键值都小的记录

    ||||||| page_rec_is_supernum(); 查看当前记录是否是该页的supermum记录,supermum记录表示比任何键值都大的记录。

    ||||||| rec_get_next_offs(): 获取相同页中下一条记录的偏移量。

    ||||||| rec_get_offsets_func(): 获取记录中每个字段的便宜

    ||||||| rec_offs_validate() 验证记录的偏移量

    ||||||| row_sel_store_mysql_rec() 函数将获取的innobase格式的行记录转化为mysql格式

    |||||||| row_sel_field_store_in_mysql_format() 函数将innobase格式的行记录中的每个字段转化为mysql格式

    |||||||| btr_pcur_store_position*(: 存储游标的位置

    ||||||||| btr_pcur_get_block(): 获取持久化游标的缓冲块

    ||||||||| btr_pcur_get_page_cur(): 获取持久化游标的页的游标

    ||||||||| page_cur_get_rec(): 获取游标位置的记录

    ||||||||| dict_index_copy_rec_order_prefix(): 拷贝记录

    |||||||||| rec_copy_prefix_to_buf(): 拷贝记录的字段到缓存buffer中

    |||||||||| dict_index_get_nth_field(): 获取第n个字段的起始地址。

    |||||||||| dict_field_get_col(): 获取第n个字段的值

    |||||| 第六阶段:移动游标到下一个索引记录

    ||||||| btr_pcur_move_to_next(): 移动持久化游标到下一条记录

    ||||||| mtr_commit(): 提交事务

      

    参考资料:http://www.it165.net/database/html/201208/2857.html

  • 相关阅读:
    21分钟 MySQL 入门教程
    git学习网址
    Unsupported major.minor version 51.0解决办法
    导入Mybatis_Spring项目遇到的问题
    SQL 模糊查询
    数据持久层
    持久化框架
    ORM
    ORM框架
    重量级框架
  • 原文地址:https://www.cnblogs.com/rgyu/p/7534077.html
Copyright © 2020-2023  润新知