Encodingチェックの強化

TritonnではSennaのインデックスを作る際、MySQLのテーブル定義情報(CREATE文、ALTER文)の情報を利用して適切な文字コードを自動的に選ぶように実装しています。この時、プログラム的にチェックが甘い部分があったのですが、またもやnkjm氏がサクッと修正してくれました!

------------------------------------------------------------------------
r73 | nkjm | 2007-06-27 15:22:14 +0900 (水, 27  6月 2007) | 13 lines
myisam/ft_update.c
        Added code to check the value of senna_encoding
myisam/ft_update.c
        Added code to check the value of senna_encoding
myisam/mi_create.c
        Added code to check the value of senna_encoding

merge履歴

というわけでmerge。

Merged from mysql-5.0-community/trunk
Added code to check the value of senna_encoding
svn merge -r72:73 mysql-5.0-community/trunk mysql-5.0-enterprise/trunk

新プロダクト MySQL Proxy リリース

MySQL Proxyなる新プロダクトがリリースされました。ただしまだver0.5.0なので安定版がでるのはかなり先だと思われますが。

MySQL Proxyとは?

MySQL Proxyは従来のMySQLクライアントとサーバの間に置くことで、以下のような機能を実現してくれるデーモンプログラムです。

  • ロードバランス
  • フェイルオーバ
  • クエリの分析
  • フィルタリング/クエリの改変
  • その他

情報源

とりあえずまだリファレンスマニュアルとかはなさげで、MySQL Forge Wikiを見るのが良さそうです。

http://forge.mysql.com/wiki/MySQL_Proxy

コメント

MySQL Clusterとかレプリケーションによる参照系の負荷分散とかをやる場合、これまでは別途ロードバランサ/ディスパッチャを用意する必要があった(Connector/Jを除く)わけですが、将来的にこのMySQL Proxyを使えばOKとなると良いですね。まあ、本気でHA構成で使う場合、こういうディスパッチャ・パタンを採用する場合はディスパッチャ自身の冗長化ができないとアレなわけですが、その辺が気になります。

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