志澤さん
こんにちは、yoku0825といいます。

サンプルコードありがとうございます。

サンプルの中ではtestFullPath_Out(UNC記法)と
testFullPathI_IN(ローカルファイル)がありますが、
実際にはCIFS経由でやっていたりしますか?
(であれば、実際にファイルが作成されるタイミングはホストしているサーバー側に隠蔽されるので、
 そういうことが起きても不思議がないかなあと思いつつ)

> →INTO OUTFILEは、対象がなくともファイルを生成するので、
>   出現するまでWhileで待ってからFile.Deleteを行う。等
INTO OUTFILEの内部動作は、
1. まずファイルが作られる
2. 行をフェッチする
3. フェッチした行はバッファにためられる
4. どこかのタイミングでバッファをfdにフラッシュ
となっていたので、
ファイルの出現タイミングが2.〜4.のどこかにズレているのだとしたら、
それはFSかOSかそのへんに欺かれているんじゃないかなぁと思います。

Console.WriteLineのあたりか、
System.IO.File.Existsの *直前* あたりに
sync()に相当する何かを押し込めると幸せになれるんじゃないかと期待しています。。


yoku0825,


2014年12月15日 15:57 志澤 敦 <atsushi.shizawa@seikodo.co.jp>:
yoku0825さん
お返事有り難うございました。

スタックトレースは未だ行なっていませんが、
実行しているのは、C#ですがこの様なフローとなります。
恐らくは、yoku0825さんのイメージ頂いているフローではないか。と考えます。

毎回発生する訳ではない辺り、
MySQLではなく、Connectorとファイルシステムとの相関によるものでは。
との推察が付いたのですが、手詰まりとなりました、、。

無理やり機能させるなら、
while(File.Exists())等で待機させれば出来なくも無いですが、
それも違うな。と言う事で引き続き解決策を検討している所です。
 →INTO OUTFILEは、対象がなくともファイルを生成するので、
  出現するまでWhileで待ってからFile.Deleteを行う。等
  →しかしながら、.NETのFile.Deleteはスレッドセーフなので、
   やはりConnector側!?と、堂々巡りに陥ってます。

------------------------------------
using System;
using System.Windows.Forms;
using MySql.Data.MySqlClient;

private void test_ctrl()
{
string host = "host_name";
string user = "userID";
string pass = "password";
string schema = "mysql";
string conString = "SERVER=" + host + ";"
+ "DATABASE=" + schema + ";"
+ "UID=" + user + ";"
+ "PASSWORD=" + pass + ";";
MySqlConnection myConnect = new MySqlConnection(conString);
myConnect.Open();

string testDir = @"\\" + host + @"\TEST\";
string testFileName = "test.tsv";
string testFullPath_Out = System.IO.Path.Combine(testDir, testFileName);
string testFullPathI_IN = @"D:\\TEST\\" + testFileName;
string SQL = @"SELECT * FROM mysql.db LIMIT 1"
+ " INTO OUTFILE '" + testFullPathI_IN + @"' FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\r\n'";
for (int i = 0; i < 1000; i++)
{
if (System.IO.File.Exists(testFullPath_Out))
{
System.IO.File.Delete(testFullPath_Out);
}
using (MySqlCommand myCommand = new MySqlCommand(SQL, myConnect))
{
try
{
myCommand.ExecuteNonQuery();
}
catch (MySqlException myEx)
{
MessageBox.Show(myEx.ToString()); //100回に数回レベルでここに到達し、「Already Exists」が発生
}
myCommand.Dispose();
}
Console.WriteLine(i.ToString());
}
MessageBox.Show("正常終了");
myConnect.Close();
myConnect.Dispose();

}

(2014/12/14 23:35), yoku ts. wrote:
こんばんは、yoku0825といいます。

原因ぽいものは全くわからないのですが、

>---検証内容---
> ・VS2012でのデバッグ時に、ステップ実行でも発生。
> ・File.Delete→INTO OUTFILEの間に、Sleepを5秒挟んだりしても発生する

これは ファイルが存在している(?)にも拘わらずFile.ExistsがTRUEで抜けてくるのが問題だと思うので、
スリープを挟むとしたらINTO OUTFILEとFile.Delete(File.Exists)の間がいいのでははないでしょうか?

1. ファイルの存在チェック
2. 存在したら消す
3. SELECT .. INTO OUTFILE ..
-- ここでブレーク --
4. ファイルの存在チェック
5. 存在したら消す
6. SELECT .. INTO OUTFILE ..

ブレークした時に、OSから見てもファイルが存在するのにFile.ExistsがFALSEになるのであれば
オブジェクトを使いまわしていないか(File.DeleteしたあとのFileオブジェクトが何を返すのかとか)とか、
OSから見てファイルがまだ存在しないのなら、mysqldのスタックなど見てみるといいのかもしれません。
5.0も5.6もselect_export::prepareの割と早い段階でcreate_fileを呼んで(ファイルだ け先行して作成される)いるので、
そこは変わらないような気がするのですが。。


yoku0825,


2014年12月12日 14:22 志澤 敦 <atsushi.shizawa@seikodo.co.jp>:
志澤と申します。
初めて投稿させて頂きます。

MySQLWindowsのケースは少ないかとも思いますが、
お心あたり御座いましたら、ご頂けると幸いです。

---環境---
OS :Windows2012 Std(Memory24GB)
DB :MySQL 5.6.21
Coccector :Net 6.9.5
FrameWork :.NET FrameWork 4.5
IDE :VS2012 Pro

---事象---
・同一ファイルパスにおいて、INTO OUTFILE →File.Deleteを高速に行うと、
 IF(File.Exists==TRUE){File.Delete}が機能せず、
SQL発行時にMySqlExceptionが発生。

・エラー内容は、「1086:already exists」

・その際、OS上にもファイルは残っており、通常のファイルとして読み書きが出 来る状態。

---検証内容---
・VS2012でのデバッグ時に、ステップ実行でも発生。
・File.Delete→INTO OUTFILEの間に、Sleepを5秒挟んだりしても発生する。
・Win2008R2でも同様に発生。
・CentOSでも同様に発生。
・MySQL5.5でも同様に発生。
--例外事象--
・MySQL5.0では発生しない。


以上となります。
DBというより、ConnectorやOS由来な気もしておりますが、
何か情報御座いましたら、ご助言の程を何卒お願い致します。