読者です 読者をやめる 読者になる 読者になる

文系プログラマによるTIPSブログ

文系プログラマ脳の私が開発現場で学んだ事やプログラミングのTIPSをまとめています。

LOAD DATAの罠:その2

mysql

続、LOAD DATAの罠を紹介。
今回は LOAD DATA のトランザクションと強制コミットについて。

初期状態はこんな感じ。


mysql> select * from t_del;
 +----+
 | id |
 +----+
 | 1 |
 +----+
1 row in set (0.00 sec)

mysql> select * from t_test;
Empty set (0.00 sec)

さて、ここから t_delをdeleteし、t_testをload dataする。
読み込むcsvと実行するためのシェルは前回と同じく、必ずDuplicateKeyErrorが起きるcsv
<loadData.sql


begin;
delete from t_del;
load data local infile 't_test.csv' into table t_test fields terminated by ',' enclosed by '' lines terminated by '\n';
commit;

では実行。t_delはrollbackされるかな?


$ ./loadData.sh
success

success。DuplicateKeyErrorなのにエラーが返らないのは前回書いた通り。
ではt_delは・・・

mysql> select * from t_del;
Empty set (0.00 sec)

・・・rollbackされない。commitされてる。
では前回と同じくSQLでわざとSyntaxErrorを起こしてみる。
<loadData.sql

begin;
delete from t_del;
orz
load data local infile 't_test.csv' into table t_test fields terminated by ',' enclosed by '' lines terminated by '\n';
commit;

これはどうなるかな。

$ ./loadData.sh
ERROR 1064 (42000) at line 3: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'orz
load data local infile 't_test.csv' into table t_test fields terminated by '' at line 1
error

errorが返った。ではt_delは・・・

mysql> select * from t_del;
Empty set (0.00 sec)

おおおお!?またしてもrollbackされない!!

調べてみた結果、オフィシャルサイトにこんな事が書いてありました。


http://dev.mysql.com/doc/refman/5.1-olh/ja/implicit-commit.html
データロード用ステートメント。LOAD DATA INFILE。MySQL 5.1.12 より前のバージョンでは、LOAD DATA INFILE は、すべてのストレージエンジンに対して暗黙的なコミットを引き起こしました。MySQL 5.1.12 の時点では、NDB ストレージエンジンを使用しているテーブルに対してのみ暗黙的なコミットを引き起こします。更なる情報については、バグ #11151 を参照してください。

どうも古いバージョンのMySQLでは、LOAD DATAは必ず暗黙的なcommitをしてしまうようで、
例えbegin; commit;としても、途中のLOAD DATAがcommitしてトランザクションを強制終了させてしまうようだ。
従って、LOAD DATAする際はトランザクション内に含めないようにしよう。

↓この記事でこれらの動作について解ったので、暇だったら見てね。
http://d.hatena.ne.jp/treeapps/20110409/1302332142