mysql create table過程 粗略了解mysql create table的過程: Cpp代碼 create table的調用路徑如下(5.1.58): do_command(sql_parse.cc) ->dispatch_command(sql_parse.cc) ->mysql_parse(sql_parse.cc) ->mysql_execute_command(sql_parse.cc) ->mysql_create_table(sql_table.cc) ->mysql_create_table_nolock(sql_table.cc),這裡會持有LOCK_open ->rea_create_table(unireg.cc) ->mysql_create_frm(unireg.cc) ->ha_create_table(handler.cc) ->handler::ha_create(handler.cc) ->ha_innodb::create(handler/ha_innodb.cc) ->create_table_def(handler/ha_innodb.cc), ->row_create_table_for_mysql(row/row0mysql.c) ->create_clustered_index_when_no_primary(handler/ha_innodb.cc)..when no primary key is defined.. ->row_create_index_for_mysql(row/row0mysql.c) ->create_index(hanler/ha_innodb.cc) ->row_table_add_foreign_constraints(row/row0mysql.c) mysql_create_table函數一開始就去持有LOCK_lock_db mutex,對creating_table++,這個值對應Com_create_table。 接下來rea_create_table首先會調用mysql_create_frm創建server層的表定義文件,然後調用ha_create_table,相應的存儲引擎會創建所需要的內容。對於innodb,則是先創建innodb層的表定義,再去創建索引,創建索引的時候,如果表定義不包含主鍵,則自動為該表創建主鍵;這也是為什麼建議innodb的表的都帶上主鍵。 如果是create table like,執行過程有所不同: Cpp代碼 create table...like...的調用路徑如下(5.1.58): ...同上... ->mysql_execute_command(sql_parse.cc) ->mysql_create_like_table(sql_table.cc),這裡需要打開源表並持有LOCK_open直到創建完frm文件 ->my_copy(mysys/my_copy.c)/mysql_create_like_schema_frm(sql_table.cc) ->ha_create_table(handler.cc) ...同上... 如果是create table like,則execute command的時候會調用mysql_create_like_table,這裡會打開源表(like之後的表,open_tables());之後開始開始創建新的表定義文件,創建新的表定義文件前會持有LOCK_open,創建完就釋放;如果源表是information_schema的表,則通過mysql_create_like_schema_frm()創建,其它的則通過my_copy(),直接copy源表的frm文件。剩下的過程就交給了存儲引擎,同普通的create table 一樣。create table like...的執行過程中也沒有對源表加鎖,但是整個過程持有LOCK_open。 如果是create table ...select,處理過程如下: Cpp代碼 create table...select...的調用路徑如下(5.1.58): ...同上... ->mysql_execute_command(sql_parse.cc) -open_and_lock_tables()--這裡對select的表加表鎖,直到整個statement完成 ->handle_select(sql_select.cc) ->mysql_select(sql_select.cc) ->JOIN::prepare(sql_select.cc,697)--這裡開始create table的過程 ->select_create::prepare(sql_insert.cc) ->create_table_from_items(sql_insert.cc,3762) ->mysql_create_table_no_lock(sql_table.cc) ...同上(create table...)... ->JOIN::optimize(sql_select.cc) ->JOIN::exec(sql_select.cc)--實際的select的過程 ->do_select(sql_select.cc) ->sub_select(sql_select.cc) ->evaluate_join_record(sql_select.cc,11585) ->end_send(sql_select.cc,12369) ->select_insert::send_data(sql_insert.cc)--插入數據的過程 ->write_record(sql_insert.cc) ->handler::ha_write_row(handler.cc) ->write_row(handler/ha_innodb.cc) 第一次看到這個邏輯,感覺有些tricky,create table竟然是在大名鼎鼎的mysql_select()過程中完成的,難道mysql認為create table...select...是select的一種特例。 create table...select...整體上分為2個過程:建表;插入數據。創建表的過程是整個select的prepare()過程中完成的(new JOIN的時候,result被初始化為select_create類型的,幾個相關類的繼承關系:select_result<-select_result_interceptor<-select_insert<-select_create;JOIN::prepare()->select_create::prepare())。而insert的過程,則是在JOIN:exec的內完成的,具體的則是在send data的時候。 需要注意的是,select的表是會被加表鎖的,直到整個操作完成(dispatch_command操作的最後會有close_thread_tables) 上面基本上是5.1 create table的處理邏輯了,5.5的處理過程也大致相同。