1. 程式人生 > >mysql 5.7原始碼 啟動監聽過程

mysql 5.7原始碼 啟動監聽過程

sql/mysqld.cc mysqld_main 

啟動主函式

  1. 主要呼叫流程
    1. MySQL啟動
    2. 主要程式碼在sql/mysqld.cc中,精簡後的程式碼如下:
      int main(int argc, char **argv) //標準入口函式
      MY_INIT(argv[0]); //呼叫mysys/My_init.c->my_init(),初始化mysql內部的系統庫
      logger.init_base(); //初始化日誌功能
      init_common_variables(MYSQL_CONFIG_NAME,argc, argv, load_default_groups) //呼叫load_defaults(conf_file_name, groups, &argc, &argv),讀取配置資訊
      user_info= check_user(mysqld_user);//檢測啟動時的使用者選項
      set_user(mysqld_user, user_info);//設定以該使用者執行
      init_server_components();//初始化內部的一些元件,如table_cache, query_cache等。
      network_init();//初始化網路模組,建立socket監聽
      start_signal_handler();// 建立pid檔案
      mysql_rm_tmp_tables() || acl_init(opt_noacl)//刪除tmp_table並初始化資料庫級別的許可權。
      init_status_vars(); // 初始化mysql中的status變數
      start_handle_manager();//建立manager執行緒
      handle_connections_sockets();//主要處理函式,處理新的連線並建立新的執行緒處理之

    3. 監聽接收連結
    4. 主要程式碼在sql/mysqld.cc中,精簡後的程式碼如下:
      THD *thd;
      FD_SET(ip_sock,&clientFDs); //客戶端socket
      while (!abort_loop)
      readFDs=clientFDs;
      if (select((int) max_used_connection,&readFDs,0,0,0) error && net->vio != 0 &&
      !(thd->killed == THD::KILL_CONNECTION))
      {
      if(do_command(thd)) //處理客戶端發出的命令
      break;
      }
      end_connection(thd);
      }

    5. 預處理連線
    6. thread_count++;//增加當前連線的執行緒
      thread_scheduler.add_connection(thd);
      for (;;) {
      lex_start(thd);
      login_connection(thd); // 認證
      prepare_new_connection_state(thd); //初始化thd描述符
      while(!net->error && net->vio != 0 &&
      !(thd->killed == THD::KILL_CONNECTION))
      {
      if(do_command(thd)) //處理客戶端發出的命令
      break;
      }
      end_connection(thd);
      }

    7. 處理
    8. do_command在sql/sql_parse.cc中:讀取客戶端傳遞的命令並分發。
      NET *net= &thd->net;
      packet_length= my_net_read(net);
      packet= (char*) net->read_pos;
      command= (enum enum_server_command) (uchar) packet[0]; //從net結構中獲取命令
      dispatch_command(command, thd, packet+1, (uint) (packet_length-1));//分發命令
      在dispatch_command函式中,根據命令的型別進行分發。
      thd->command=command;
      switch( command ) {
      case COM_INIT_DB: ...;
      case COM_TABLE_DUMP: ...;
      case COM_CHANGE_USER: ...;
      ….
      case COM_QUERY: //如果是查詢語句
      {
      alloc_query(thd, packet, packet_length)//thd->set_query(query, packet_length);
      mysql_parse(thd, thd->query(), thd->query_length(), &end_of_stmt);
      // 解析查詢語句
      ….
      }

      在mysql_parse函式中,
      lex_start(thd);
      if (query_cache_send_result_to_client(thd, (char*) inBuf, length) sql_command

      在mysql_execute_command中,根據命令型別,轉到相應的執行函式。
      switch (lex->sql_command) {
      LEX *lex= thd->lex;
      TABLE_LIST *all_tables;
      case SQLCOM_SELECT:
      check_table_access(thd, lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL, all_tables, UINT_MAX, FALSE); //檢查使用者許可權
      execute_sqlcom_select(thd, all_tables); //執行select命令
      break;

      case SQLCOM_INSERT:
      { res= insert_precheck(thd, all_tables) //rights
      mysql_insert(thd, all_tables, lex->field_list, lex->many_values,
      lex->update_list, lex->value_list,
      lex->duplicates, lex->ignore);
      break;
      在execute_sqlcom_select函式中,
      res= open_and_lock_tables(thd, all_tables)//directly and indirectly
      res= handle_select(thd, lex, result, 0);

      handle_select在sql_select.cc中,呼叫mysql_select ,在mysql_select中,
      join->prepare();//Prepare of whole select (including sub queries in future).
      join->optimize();//global select optimisation.
      join->exec();//

      在mysql_insert函式中,
      open_and_lock_tables(thd, table_list)
      mysql_prepare_insert(); //prepare item in INSERT statment
      while ((values= its++))
      write_record(thd, table ,&info);//寫入新的資料

      在write_record函式中,
      table->file->ha_write_row(table->record[0])
      ha_write_row在Handler.cc中,只是一個介面
      write_row(buf); //呼叫表儲存所用的引擎

  2. 當客戶端連結上mysql服務端時,系統為其分配一個連結描述符thd,用以描述客戶端的所有資訊,將作為引數在各個模組之間傳遞。一個典型的客戶端查詢在MySQL的主要模組之間的呼叫關係如下圖所示:

    當mysql啟動完畢後,呼叫handle_connection_sockets等待客戶端連線。當客戶端連線上伺服器時,服務處理函式將接受連 接,會為其建立連結執行緒,並進行認證。如認證通過,每個連線執行緒將會被分配到一個執行緒描述符thd,可能是新建立的,也可能是從 cached_thread執行緒池中複用的。該描述符包含了客戶端輸入的所有資訊,如查詢語句等。伺服器端會層層解析命令,根據命令型別的不同,轉到相應 的sql執行函式,進而給傳遞給下層的儲存引擎模組,處理磁碟上的資料庫檔案,最後將結果返回。執行完畢後thd將被加入cached_thread中。