主要模塊及數據流
通過多年的發展,mysql的主要模塊已經穩定,基本不會有大的修改。本文將對MySQL的總體架構及重要目錄進行講述。
mysql
bool set_db(const char *new_db, size_t new_db_len) void set_query(char *query_arg, uint32 query_length_arg); { pthread_mutex_lock(&LOCK_thd_data); set_query_inner(query_arg, query_length_arg); pthread_mutex_unlock(&LOCK_thd_data); }
unsigned char *buff,*buff_end,*write_pos,*read_pos; //緩存相關 unsigned long remain_in_buf,length, buf_length, where_b; unsigned long max_packet,max_packet_size; //當前值;最大值 unsigned int pkt_nr,compress_pkt_nr; //當前(未)壓縮包的順序值 my_bool compress; //是否壓縮 unsigned int write_timeout, read_timeout, retry_count; //最大等待時間 unsigned int *return_status; //thd中的服務器狀態 unsigned char reading_or_writing;
enum utype { NONE,DATE,SHIELD,NOEMPTY,CASEUP,PNR,BGNR,PGNR,YES,NO,REL, CHECK,EMPTY,UNKNOWN_FIELD,CASEDN,NEXT_NUMBER,INTERVAL_FIELD, BIT_FIELD, TIMESTAMP_OLD_FIELD, CAPITALIZE, BLOB_FIELD, TIMESTAMP_DN_FIELD, TIMESTAMP_UN_FIELD, TIMESTAMP_DNUN_FIELD};
#define max(a, b) ((a) > (b) ? (a) : (b)) //得出兩數中的大者 do \ { \ char compile_time_assert[(X) ? 1 : -1] \ __attribute__ ((unused)); \ } while(0)
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); }
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); }
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); //調用表存儲所用的引擎