zoukankan      html  css  js  c++  java
  • mysql源码分析-启动过程

    mysql源码分析-启动过程

    概要

    # sql/mysqld.cc, 不包含psi的初始化过程
    mysqld_main:
        // 加载my.cnf和my.cnf.d,还有命令行参数
        if (load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv))
            return 1;
        init_sql_statement_names();
        sys_var_init();
        init_error_log_mutext();
        mysql_audit_initialize();
    
        logger.init_base();
    
        // 读取和设置配置文件和命令行参数,并根据相关参数进行相应的初始化操作,这个函数相当庞大
        if (init_common_variables())
            unireg_abort(1);
        
        init_signals();
        
        if (init_server_components())
            unireg_abort(1);
    
        init_ssl();
        // 网络初始化,获取监听地址,监听unix_socket,开始监听
        network_init();
        
        if (mysql_rm_tmp_tables() || 
            acl_init(opt_noacl) ||
            my_tz_init((THD *)0, default_tz_name, opt_bootstrap))
        { ... }
    
        if (!opt_noacl)
            grant_init();
        if (!opt_bootstrap)    
            servers_init(0);
        
        init_status_vars();
    
        start_handle_manager();
    
        sql_print_information(...);
    
        handle_connections_sockets();
    
        mysql_mutex_lock(&LOCK_thread_count);
        while (!ready_to_exit) 
            mysql_cond_wait(&COND_thread_count, &LOCK_thread_count)
        mysql_mutex_unlock(&LOCK_thread_count)
    
    init_common_variables:
        // 设置数据库默认的存储引擎
    #if defined(WITH_INNOBASE_STORAGE_ENGINE) || defined(WITH_XTRADB_STORAGE_ENGINE)
          default_storage_engine= const_cast<char *>("InnoDB");
    #else
          default_storage_engine= const_cast<char *>("MyISAM");
    #endif
        // 添加show status里的一些变量
        if (add_status_vars(status_vars))
        return 1; 
        
        // 解析命令行参数
        // 根据thread_handling设置thread_scheduler(也就是thd->scheduler), scheduler实现在sql/scheduler.cc和sql/mysqld.cc,目前有两种模型,one-thread-per-connection和no-threads
        if (get_options(&remaining_argc, &remaining_argv))
            return 1;
        //其他,超级庞大
    
    network_init:
        // 
    
    handle_connections_sockets:
        // poll mysqld监听的socket(tcp,unix), 代码省略
        // 新建vio实例,其实就是绑定不同的通信实例(有windows的namedpipe, 平台独立的shmem, 还有支持openssl,其他类型的连接统一处理)
        // 配置一些socket 选项
        if (!(vio_tmp = vio_new(new_sock,
                                sock == unix_sock ? VIO_TYPE_SOCKET : VIO_TYPE_TCPIP,
                                sock == unix_sock ? VIO_LOCALHOST : 0)) ||
            // 绑定THD和vio实例
            my_net_init(&thd->net, vio_tmp))
        {
            // 失败处理,省略
        }
        // 设置一些THD实例的统计信息,如连接数,检查连接数是否超出上线,触发thd->scheduler->add_connection方法 
        // 新建pthread执行handle_one_connection处理请求, 在sql/sql_connect.cc中定义
        create_new_thread(thd)
    
    // sql/sql_connect.cc
    handle_one_connetion:
        do_handle_one_connection(thd)
    
    do_handle_one_connection:
        // 统计slow_launch_threads, 代码省略
        for (;;) { // 此处死循环是为了复用thd,下次直接初始化新的connection信息,处理下一个connection
            // 用户认证,初始化请求信息,
            if (thd_prepare_connection(thd)) { // 错误处理,省略}
        
            while (thd_is_connection_alive(thd)) {
                // 通知plugin->release_thd,然后unlock thd->audit_class_plugins中的plugins
                mysql_audit_release(thd);
                if (do_command(thd))
                    break;    
            }
        }
    
    // sql/sql_parse.cc, 省略对WITH_WSREP的处理,wsrep thd有很多特别的处理步骤
    do_command:
        if (packet_length = mysql_net_read(net)) == packet_error) { // 错误处理,省略}
        
        // 获取请求消息的起始位置
        packet = (char*) net->read_pos;
        // 从请求消息中获取mysql命令, include/mysql_com.h中有定义所有的mysql 支持的命令
        command = (enum enum_server_command) (uchar) packet[0];
        return_value = dispatch_command(command, thd, packet+1, (uint) (packet_length-1));
    
    // sql/sql_parse.cc, 超级庞大
    dispatch_command:
        // 根据command来switch不同的分支,执行不同的mysql命令,执行sql语句为COM_QUERY,或者COM_STMT_EXCUTE(预处理sql语句)
        // case COM_QUERY:
        mysql_parse(thd, thd->query(), thd->query_length(), &parser_state);
    
    // sql/sql/parse.cc
    mysql_parse:
        # 解析sql语句
        parse_sql(thd, parser_state, NULL);
        # 如果发现分号,就开始执行sql语句
        mysql_execute_command(thd)
    
    mysql_execute_command:
        # 根据解析出来的sql command执行不同的命令,基本上在mysql命令行敲的每个命令都对应一个分支,比如begin(SQLCOM_BEGIN),select(SQL_SELECT)等
    

    参看

    1. https://dev.mysql.com/doc/internals/en/
  • 相关阅读:
    c# 自定義事件
    c# 判斷事件中鼠標的左右按鍵
    I swear(我發誓)
    SQL Server实用操作小技巧集合
    富人和穷人的经典差异
    Mssql入门语句
    c# 匿名方法學習
    SOS: Autodesk MapGuide Studio Preview can not display "Feature Label" with Chinese text on the platform of MapGuide Open Source
    MapGuide open source开发心得二: 资源
    moblie development based on .net compact framework2 solution:activeX
  • 原文地址:https://www.cnblogs.com/zhedan/p/12454394.html
Copyright © 2011-2022 走看看