sql >> データベース >  >> RDS >> Mysql

MySQL C#非同期メソッドが機能しませんか?

    いくつかの古いコード(6.7.2)から判断すると、mysqlADO.NETプロバイダーは非同期機能を正しく実装していないようです。これには、TAPパターンと古いスタイルのBegin ...、End...非同期パターンが含まれます。そのバージョンでは、Db*非同期メソッドはまったく記述されていないように見えます。 .NETの基本クラスのものを使用します。これらは同期しており、すべて次のようになります。

    public virtual Task<int> ExecuteNonQueryAsync(...) {
        return Task.FromResult(ExecuteNonQuery(...));
    }
    

    (タスクでラップするという追加のオーバーヘッドと100%同期します。参照元はこちら )

    開始バージョンと終了バージョンが正しく記述されている場合(正しく記述されていない場合)、次のように実装できます。

    public override Task<int> ExecuteNonQueryAsync(...) {
        return Task<int>.Factory.FromAsync(BeginExecuteNonQueryAsync, EndExecuteNonQueryAsync, null);
    }
    

    SqlCommandのそのメソッドの参照ソース

    これを行うには、基になるソケットのある種のコールバックAPIに依存して、呼び出し元がソケットを介してバイトを送信し、登録されたメソッドが準備ができたときに基になるネットワークスタックからコールバックされるパターンで最終的に処理します。

    ただし、mysqlコネクタはこれを行いません(最初からそのメソッドをオーバーライドしませんが、オーバーライドした場合、関連するbeginメソッドとendメソッドは一部の基盤となるソケットAPIで非同期ではありません)。 mysqlコネクタの機能代わりに 現在の接続インスタンスで内部メソッドへのデリゲートを構築し、別のスレッドで同期的に呼び出します。その間、たとえば、同じ接続で次のような2番目のコマンドを実行することはできません。

    private static void Main() {
        var sw = new Stopwatch();
        sw.Start();
        Task.WaitAll(
            GetDelayCommand().ExecuteNonQueryAsync(),
            GetDelayCommand().ExecuteNonQueryAsync(),
            GetDelayCommand().ExecuteNonQueryAsync(),
            GetDelayCommand().ExecuteNonQueryAsync(),
            GetDelayCommand().ExecuteNonQueryAsync(),
            GetDelayCommand().ExecuteNonQueryAsync(),
            GetDelayCommand().ExecuteNonQueryAsync(),
            GetDelayCommand().ExecuteNonQueryAsync(),
            GetDelayCommand().ExecuteNonQueryAsync(),
            GetDelayCommand().ExecuteNonQueryAsync(),
            GetDelayCommand().ExecuteNonQueryAsync(),
            GetDelayCommand().ExecuteNonQueryAsync());
        sw.Stop();
        Console.WriteLine(sw.Elapsed.Seconds);
    }
    
    private static DbCommand GetDelayCommand() {
        var connection = new MySqlConnection (...);
        connection.Open();
        var cmd = connection.CreateCommand();
        cmd.CommandText = "SLEEP(5)";
        cmd.CommandType = CommandType.Text;
        return cmd;
    }
    

    (接続プールであり、タスクの数が最大プールサイズを超えていると仮定します。非同期が機能した場合、このコードは、プール内の接続の数とその両方に依存する数ではなく、プール内の接続の数に応じた数を取得します。同時に実行できるスレッド)

    これは、コードにドライバーをロックする (ネットワーク内部を管理する実際のもの; *)。そうでない場合(そして内部はスレッドセーフであり、接続プールを管理するために他の方法が使用された場合)基になるネットワークストリームでブロッキング呼び出しを実行します

    そうですね、このコードベースには非同期サポートはありません。誰かが私にコードを教えてくれれば、新しいドライバーを見ることができますが、内部の NetworkStreamが疑われます ベースのオブジェクトは大きく異なって見えることはなく、非同期コードもそれほど異なって見えません。 async サポートするドライバーは、それを行う非同期の方法に依存するように内部のほとんどを記述し、同期コードの同期ラッパーを持ちます。または、 SqlClientのようになります。 ソースを参照し、いくつかのタスクに依存します ライブラリをラッピングして、同期実行と非同期実行の違いを抽象化します。

    *ドライバーをロックすることは、非ブロッキングIOを使用できない可能性があることを意味するのではなく、メソッドをロックステートメントで記述して非ブロッキングBegin / End IAsyncResult> TAPパターンの前に記述された可能性のあるコード。

    編集:ダウンロード6.9.8;疑われるように、機能している非同期コード(非ブロッキングIO操作)はありません。ここにバグが報告されています:https://bugs.mysql.com/bug。 php?id =70111

    2016年7月6日更新:GitHubの興味深いプロジェクトで、最終的に https://github.com/ mysql-net / MySqlConnector (おそらく、成功に関与しているより多くの貢献者を使用することができます[私はもうMySqlで何も作業していません])。



    1. CentOS7では、MySQLを起動できません

    2. 一意の識別子なしで重複する行を削除する方法

    3. MySQL列挙型データ型のデフォルト値を「いいえ」に設定するにはどうすればよいですか?

    4. MySQL:同じMySqlインスタンスでMySQLデータベースのクローンを作成する