文章目錄
在上一篇文章中我們講到了的 mysql_execute_command,這個函數根據解析出來的SQL命令分別調用不同的函數做進一步處理。我們這裡先看"INSERT"命令的處 理流程。其對應的處理函數是mysql_insert,在sql/sql_insert.cc中,還是很長,大概300多行。
bool mysql_insert(THD *thd, TABLE_LIST *table_list, // 該命令要用到的表 List<Item> &fields, // 使用的域 List<List_item> &values_list, List<Item> &update_fields, List<Item> &update_values, enum_duplicates duplic, bool ignored) { open_and_lock_tables(thd, table_list); mysql_prepare_insert(...); foreach value in values_list { write_record(...); }}其實裡面還有很多處理trigger,錯誤,view之類的,我們暫時都忽略。 // 寫資料記錄int write_record(THD *thd, TABLE *table,COPY_INFO *info) { if (info->handle_duplicates == DUP_REPLACE || info->handle_duplicates == DUP_UPDATE) { table->file->ha_write_row(table->record[0]); table->file->ha_update_row(table->record[1], table->record[0])); } else { table->file->ha_write_row(table->record[0]); }} 不用說,這裡我們還是省略了好多東西,要注意的是這裡調用的table->file->ha_write_row和table->file->ha_update_row。在sql/table.h可以看到table的定義,其中file被定義成handler *file; 那 handler是什嗎?對了,這就是我們前面提到的資料存放區抽象層,所有的儲存引擎都必須事先這裡定義的介面,才能被mysql使用。在這裡使用的具體的 介面操作是ha_write_row和ha_update_row。這兩個函數可以在sql/handler.cc中看到。比如 ha_write_row:int handler::ha_write_row(uchar *buf) { write_row(buf); // 調用具體的實現 binlog_log_row(table, 0, buf, log_func)); // 寫binlog} 下面我們看看在myisam中是怎麼實現的檔案操作,代碼在storage/myisam/ha_myisam.cc中。先看write_row: 723 int ha_myisam::write_row(uchar *buf) 724 { 725 ha_statistic_increment(&SSV::ha_write_count); 726 727 /* If we have a timestamp column, update it to the current time */ 728 if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) // 如果有timestamp域,寫入目前時間。 729 table->timestamp_field->set_time(); 730 731 /* 732 If we have an auto_increment column and we are writing a changed row 733 or a new row, then update the auto_increment value in the record. 734 */ 735 if (table->next_number_field && buf == table->record[0]) // 更新auto_increment列 736 { 737 int error; 738 if ((error= update_auto_increment())) 739 return error; 740 } 741 return mi_write(file,buf); // 真正寫檔案 742 } 再看mi_write函數,很好找,就在storage/myisam/mi_write.c,我們就不再分析下去了,具體實現和myisam使用的檔案格式相關,有興趣的可以參考myisam的相關文檔。 結語寫到這裡,我們對於mysql執行sql語句的主要調用流程就有了大概的瞭解,但是真正的痛點往往在細節中,我也刻意逃避了這些細節,但是還是應該列一下相關的內容:+ Sql語句的解析和相關資料結構+ Sql語句的描述資料結構+ 執行最佳化相關演算法+ 資料存放區殷勤抽象層的定義和互動+ 儲存引擎的具體操作和檔案格式
必須要提到的是,這些地方的代碼都比較難懂,而且核心函數都很長,非常不便與理解,有需要的人可以選一些方面具體深入,但要面面俱到就需要很多時間了。