5

.sql ファイル (550 MB) があり、実行中の mysql サーバーにインポートしたいと考えています。mysql.exe へのパスを知っています。

私の考えは、コマンド ラインの import を模倣することですmysql -u user -ppass db_name < file.sql。これはコマンド ラインからうまく機能します (max_allowed_pa​​cket を高く設定しました)。ここStackoverflowの別のスレッドによると、これが機能していることがわかりました:

Process process = new Process();
process.StartInfo.FileName = mysqlexepath;
process.StartInfo.Arguments = "-v -u user -ppassworddbname";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;

try
{
    process.Start();
    StreamWriter input = process.StandardInput;
    using (StreamReader sr = new StreamReader(sqlfilepath))
    {
        while ((line = sr.ReadLine()) != null)
        {
            if (process.HasExited == true)
                throw new Exception("DB went away.");

            input.WriteLine(line);
            input.Flush();
        }
    }
    process.Close();
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}

DBでテーブルが作成されている様子がわかります。しかし、私の問題は、プロセスの約半分が終了することです。いくつかのタイムアウト設定をグーグルで検索しましたが、何も見つかりませんでした。

私も最初にファイルを読み取ろうとしました:

var file = FileInfo(sqlfilepath);
StreamReader reader = file.OpenText();
string fileContents = reader.ReadToEnd();
StreamWriter input = process.StandardInput;
input.AutoFlush = true;
input.Write(fileContents);
input.Close();

しかし、OutOfMemory 例外が発生します。したがって、適切な方法は文字列を通り抜けません。

どこに問題があるのか​​ を調べる方法についてアドバイスをいただければ幸いです。そのプロセスのタイムアウトかmysqlのタイムアウトか、問題がStreamReaderにあるのかさえわかりません。

4

4 に答える 4

16

これがあなたの問題に対する直接的な答えではないことはわかっていますが、正直なところ、あなたのアプローチの何が問題なのかわかりません。mysql.exe を使用して非常に大きな SQL スクリプトを実行する方法を共有することで支援できます...

"C:\Program Files (x86)\MySQL\MySQL Server 5.0\bin\mysql.exe" -C -B --password=[password] -P 3306 --user=[username] --host=localhost --database=[database] -e "\. C:\Backups\Mybackup.sql"

これらのパラメータのほとんどは明らかで、接続情報などです。

明らかでないのは、mysql が次のコマンドを実行して終了するように指定し-e "\. [filename]"たパラメーターの魔法の部分です。-eプレフィックス"\. "は、入力ファイルを使用する必要があることを示し、その後にそのファイル名が続きます。

これを使用して、数ギガバイトのデータベースを問題なく復元します。したがって、ここにmssqlを使用した完全な「スクリプトの実行」があります...

public static int RunMySql(string server, int port, string user, string password, string database, string filename)
{
    var process = Process.Start(
        new ProcessStartInfo
        {
            FileName = @"C:\Program Files (x86)\MySQL\MySQL Server 5.0\bin\mysql.exe",
            Arguments =
                String.Format(
                    "-C -B --host={0} -P {1} --user={2} --password={3} --database={4} -e \"\\. {5}\"",
                    server, port, user, password, database, filename),
            ErrorDialog = false,
            CreateNoWindow = true,
            UseShellExecute = false,
            RedirectStandardError = true,
            RedirectStandardInput = true,
            RedirectStandardOutput = true,
            WorkingDirectory = Environment.CurrentDirectory,
        }
        );

    process.OutputDataReceived += (o, e) => Console.Out.WriteLine(e.Data);
    process.ErrorDataReceived += (o, e) => Console.Error.WriteLine(e.Data);
    process.Start();
    process.BeginErrorReadLine();
    process.BeginOutputReadLine();
    process.StandardInput.Close();
    process.WaitForExit();

    return process.ExitCode;
}
于 2012-12-04T18:34:11.207 に答える
0

.NET アプリケーションをデバッグする場合は、windbg+SOS が最適なツールです。

于 2012-12-07T15:28:44.803 に答える
0

私は非常に多くの問題に直面してきました。問題はコードではなく、コードは正しいです。問題は、コンピューターがプロセスあたりのメモリ容量が大きいファイルの操作をサポートしていない仮想メモリの制限です。Windows プロセスのシステムは、システムのクラッシュを防ぐために、各プロセスを実行するメモリの量を制限します。

コンピューターのアーキテクチャやメモリ、バスの量などによって異なるため、限界はわかりません..

ファイルからのアドバイスは、順番にテーブルを作成し、ピースランを読んだり、別のランを読んだりすることです。

別のアイデアは、別のスレッドまたはプロセスで並行して作業することです。これを見てください: http://www.codeproject.com/Articles/189374/The-Basics-of-Task-Parallelism-via-C

于 2012-12-04T11:09:23.203 に答える