Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Phương thức không đồng bộ MySQL C # không hoạt động?

Đánh giá từ một số mã cũ (6.7.2), có vẻ như nhà cung cấp mysql ADO.NET không triển khai bất kỳ chức năng không đồng bộ nào một cách chính xác. Điều này bao gồm mẫu TAP và các mẫu không đồng bộ kiểu cũ hơn Bắt đầu ..., Kết thúc .... Trong phiên bản đó, các phương thức Db * không đồng bộ dường như không được viết; họ sẽ sử dụng các lớp cơ sở trong .NET đồng bộ và tất cả trông giống như sau:

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

(Đồng bộ 100% với chi phí bổ sung khi gói nó trong một tác vụ; nguồn tham khảo tại đây )

Nếu phiên bản Bắt đầu và Kết thúc được viết chính xác (chúng không đúng), nó có thể được triển khai như sau:

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

( nguồn tham chiếu cho phương pháp đó cho SqlCommand )

Thực hiện điều này phụ thuộc vào một số loại api gọi lại cho ổ cắm bên dưới để cuối cùng xử lý theo một mẫu trong đó người gọi gửi một số byte qua ổ cắm và sau đó một phương thức đã đăng ký sẽ được gọi lại từ ngăn xếp mạng bên dưới khi nó sẵn sàng.

Tuy nhiên, trình kết nối mysql không làm điều này (nó không ghi đè phương thức đó ngay từ đầu; nhưng nếu có, các phương thức bắt đầu và kết thúc có liên quan sẽ không đồng bộ hóa trên một số api ổ cắm bên dưới). Trình kết nối mysql hoạt động gì thay vào đó là xây dựng một đại biểu cho một phương thức nội bộ trên cá thể kết nối hiện tại và gọi nó một cách đồng bộ trên một luồng riêng biệt. Trong thời gian chờ đợi, ví dụ:bạn không thể thực hiện lệnh thứ hai trên cùng một kết nối, giống như sau:

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

(giả sử bạn đang gộp kết nối và số lượng tác vụ ở đó nhiều hơn kích thước nhóm tối đa; nếu async hoạt động, mã này sẽ nhận được một số tùy thuộc vào số lượng kết nối trong nhóm thay vì một số tùy thuộc vào cả điều đó và số lượng các chuỗi có thể chạy đồng thời)

Điều này là do mã có khóa trình điều khiển (thứ thực tế quản lý mạng nội bộ; *). Và nếu nó không (và các phần bên trong không phải là chuỗi an toàn và một số cách khác được sử dụng để quản lý nhóm kết nối) nó tiếp tục thực hiện chặn cuộc gọi trên luồng mạng bên dưới .

Vì vậy, không có hỗ trợ async trong tầm nhìn cho cơ sở mã này. Tôi có thể xem trình điều khiển mới hơn nếu ai đó có thể trỏ tôi đến mã, nhưng tôi nghi ngờ NetworkStream nội bộ các đối tượng dựa trên trông không khác biệt đáng kể và mã không đồng bộ trông cũng không khác nhiều. async trình điều khiển hỗ trợ sẽ có hầu hết các nội dung được viết để phụ thuộc vào một cách làm việc không đồng bộ và có một trình bao bọc đồng bộ cho mã đồng bộ; cách khác, nó sẽ giống SqlClient nhiều hơn nguồn tham khảo và phụ thuộc vào một số Task gói thư viện để loại bỏ sự khác biệt giữa chạy đồng bộ hoặc không đồng bộ.

* khóa trên trình điều khiển không có nghĩa là nó không thể sử dụng IO không chặn, chỉ là phương pháp này không thể được viết bằng câu lệnh khóa và sử dụng mã Begin / End IAsyncResult mã có thể đã được viết trước các mẫu TAP.

Chỉnh sửa:đã tải xuống 6.9.8; như nghi ngờ không có mã không đồng bộ hoạt động (hoạt động IO không chặn); có một lỗi được gửi ở đây: https://bugs.mysql.com/bug. php? id =70111

Cập nhật ngày 6 tháng 7 năm 2016:dự án thú vị trên GitHub mà cuối cùng có thể giải quyết vấn đề này tại https://github.com/ mysql-net / MySqlConnector (có lẽ có thể sử dụng nhiều cộng tác viên đóng góp vào thành công của nó [Tôi không còn làm việc với MySql nữa]).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách tốt nhất để loại bỏ giá trị khỏi trường SET?

  2. Tùy chỉnh các phím tắt trong MySql Workbench

  3. MySQLdb bằng Python:Không thể kết nối với máy chủ MySQL trên 'localhost'

  4. Khóa SQL, MUL so với PRI và UNI

  5. MySQLi có xác minh chứng chỉ máy chủ theo mặc định khi sử dụng SSL không?