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を実行してバイナリログをテキスト表示する)マシンのハードディスクに空きがあるかどうかという話だと思われる。