LOAD DATAコマンドを調べる
SQLパーサ部分
sql/sql_yacc.yyにて。SQLコマンドはSQLCOM_LOADらしい。
load_data: load_data_lock opt_local INFILE TEXT_STRING_filesystem { LEX *lex=Lex; lex->sql_command= SQLCOM_LOAD; lex->lock_option= $1; lex->local_file= $2; lex->duplicates= DUP_ERROR; lex->ignore= 0; if (!(lex->exchange= new sql_exchange($4.str, 0))) MYSQL_YYABORT; }
dispatch部分
sql/sql_parse.ccのmysql_execute_command関数のswitch-caseにて。mysql_load関数が処理する。
case SQLCOM_LOAD: { 〜中略〜 res= mysql_load(thd, lex->exchange, first_table, lex->field_list, lex->update_list, lex->value_list, lex->duplicates, lex->ignore, (bool) lex->local_file); break; }
mysql_load関数
sql/sql_load.ccのmysql_load関数より抜粋。
対象テーブルにロックをかける。
if (open_and_lock_tables(thd, table_list))
トランザクション対応テーブルかどうかを調べる。
transactional_table= table->file->has_transactions();
バルクインサート実行。
table->file->start_bulk_insert((ha_rows) 0);
おまけ
LOAD DATAを実行した後、mysqlbinlogで確認すると、インポートに使用したファイルと同じ内容のファイルが/tmp以下に生成されていてそこからLOAD DATAするように書かれている。
こんな感じ。
# at 316 #070627 10:16:12 server id 1 end_log_pos 450 Execute_load_query thread_id=1 exec_time=0 error_code=0 SET TIMESTAMP=1182906972/*!*/; load data LOCAL INFILE '/tmp/SQL_LOAD_MB-1-1' INTO table t1/*!*/; # file_id: 1
この/tmp/SQL_LOAD_MB-1-1なんてファイルはオイラは知らねという話。
実はこれは、mysqldがやっていることではなく、LOAD DATA処理により発生したbulk insert文をリストア時にさらに高速化するために、mysqlbinlogコマンドがやっていること。
client/mysqlbinlog.ccにて。
int Load_log_processor::process(Begin_load_query_log_event *blqe) { return process_first_event("SQL_LOAD_MB", 11, blqe->block, blqe->block_len, blqe->file_id, 0); }
Load_log_processor::process関数のDescription。
Creates temporary file to be used in LOAD DATA and writes first block of data to it. Registers its file name (and optional Create_file event) in the array of active temporary files.
従って、mysqldが稼働しているサーバで、大量データをLOAD DATAコマンドでインポートするときに/tmpを含むパーティションがいっぱいになってしまうとか心配する必要はなくて、敢えて留意するとしたら、mysqlbinlogを使ってリストアする(正確にいうとmysqlbinlogを実行してバイナリログをテキスト表示する)マシンのハードディスクに空きがあるかどうかという話だと思われる。