Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Metode async MySQL C# tidak berfungsi?

Dilihat dari beberapa kode lama (6.7.2), tampaknya penyedia mysql ADO.NET tidak mengimplementasikan fungsi async dengan benar. Ini termasuk pola TAP dan gaya lama Begin..., End... pola async. Dalam versi itu, metode async Db* tampaknya tidak ditulis sama sekali; mereka akan menggunakan kelas dasar di .NET yang sinkron dan semuanya terlihat seperti:

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

(100% sinkron dengan overhead tambahan untuk membungkusnya dalam tugas; sumber referensi di sini )

Jika versi Begin dan End ditulis dengan benar (tidak) itu bisa diimplementasikan seperti ini:

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

(sumber referensi untuk metode tersebut untuk SqlCommand )

Melakukan ini tergantung pada semacam api panggilan balik untuk soket yang mendasarinya untuk akhirnya menangani pola di mana pemanggil mengirim beberapa byte melalui soket dan kemudian metode terdaftar dipanggil kembali dari tumpukan jaringan yang mendasarinya ketika sudah siap.

Namun, konektor mysql tidak melakukan ini (itu tidak menimpa metode itu di tempat pertama; tetapi jika ya, metode awal dan akhir yang relevan tidak asinkron pada beberapa api soket yang mendasarinya). Apa yang dilakukan konektor mysql sebagai gantinya adalah membangun delegasi ke metode internal pada instance koneksi saat ini dan memanggilnya secara sinkron pada utas terpisah. Anda tidak dapat sementara, misalnya, menjalankan perintah kedua pada koneksi yang sama, seperti ini:

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;
}

(dengan asumsi Anda adalah kumpulan koneksi dan jumlah tugas di sana lebih dari ukuran kumpulan maksimum; jika async berfungsi, kode ini akan mendapatkan nomor tergantung pada jumlah koneksi di kumpulan alih-alih nomor tergantung pada itu dan jumlah utas yang dapat berjalan secara bersamaan)

Ini karena kode memiliki mengunci driver (hal aktual yang mengelola internal jaringan; *). Dan jika tidak (dan internal dinyatakan aman dan beberapa cara lain digunakan untuk mengelola kumpulan koneksi) ini melanjutkan untuk melakukan panggilan pemblokiran pada aliran jaringan yang mendasarinya .

Jadi ya, tidak ada dukungan async yang terlihat untuk basis kode ini. Saya dapat melihat driver yang lebih baru jika seseorang dapat mengarahkan saya ke kode tersebut, tetapi saya menduga NetworkStream internal objek berbasis tidak terlihat berbeda secara signifikan dan kode async juga tidak terlihat jauh berbeda. Sebuah async driver pendukung akan memiliki sebagian besar internal yang ditulis bergantung pada cara asinkron untuk melakukannya dan memiliki pembungkus sinkron untuk kode sinkron; alternatifnya akan lebih mirip SqlClient sumber referensi dan bergantung pada beberapa Task membungkus perpustakaan untuk mengabstraksikan perbedaan antara menjalankan secara sinkron atau asinkron.

* mengunci driver tidak berarti tidak mungkin menggunakan IO non-pemblokiran, hanya saja metode tersebut tidak dapat ditulis dengan pernyataan kunci dan menggunakan kode Mulai/Akhir yang tidak memblokir IAsyncResult kode yang bisa ditulis sebelum pola TAP.

Sunting:diunduh 6.9.8; seperti yang diduga tidak ada kode asinkron yang berfungsi (operasi IO non-pemblokiran); ada bug yang diajukan di sini:https://bugs.mysql.com/bug. php?id=70111

Perbarui 6 Juli 2016:proyek menarik di GitHub yang akhirnya dapat mengatasi ini di https://github.com/ mysql-net/MySqlConnector (mungkin dapat menggunakan lebih banyak kontributor yang memiliki andil dalam keberhasilannya [Saya tidak lagi mengerjakan apa pun dengan MySql]).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Urutan acak dengan Entity Framework dan MySQL

  2. kueri mySQL:Bagaimana cara memasukkan dengan UNION?

  3. Kesalahan MySQL 1215:Tidak dapat menambahkan batasan kunci asing

  4. Bagaimana cara mengisi tampilan grid dengan mysql?

  5. PILIH banyak ke banyak tabel dalam satu kueri