2017-04-26 56 views
10

Tôi có TcpListener lớp và tôi đang sử dụng async/await đọc và viết.C# Mysql - Sử dụng khóa trên truy vấn cơ sở dữ liệu cho máy chủ async chờ đợi

Đối với máy chủ này, tôi đã tạo một cá thể cơ sở dữ liệu duy nhất mà tôi đã chuẩn bị tất cả các truy vấn cơ sở dữ liệu.

Nhưng sau đó cho thêm một TcpClient Tôi muốn nhận những ngoại lệ:

Một ngoại lệ của loại MySql.Data.MySqlClient.MySqlException xảy ra trong MySql.Data.dll nhưng không được xử lý theo mã người dùng

Thông tin thêm: Hiện đã một là mở DataReader liên kết với số này Connection phải được đóng trước tiên.

Nếu tôi hiểu chính xác thì không thể có nhiều hơn một truy vấn cơ sở dữ liệu vào thời điểm đó là vấn đề với nhiều khách hàng async.

Vì vậy, tôi chỉ cần thêm khóa trong truy vấn của tôi như thế này và mọi thứ có vẻ ổn.

// One MySqlConnection instance for whole program. 

    lock (thisLock) 
    { 
    var cmd = connection.CreateCommand(); 

    cmd.CommandText = "SELECT Count(*) FROM logins WHERE username = @user AND password = @pass"; 
    cmd.Parameters.AddWithValue("@user", username); 
    cmd.Parameters.AddWithValue("@pass", password); 

    var count = int.Parse(cmd.ExecuteScalar().ToString()); 
    return count > 0; 
} 

Tôi cũng đã thử phương pháp này với usings mà tạo kết nối mới cho mỗi truy vấn như đã đề cập từ một người nào đó của SO cộng đồng nhưng phương pháp này là nhiều hơn nữa chậm hơn so với ổ khóa:

using (MySqlConnection connection = new MySqlConnection(connectionString)) 
    { 
     connection.Open(); // This takes +- 35ms and makes worse performance than locks 

     using (MySqlCommand cmd = connection.CreateCommand()) 
     { 
      cmd.CommandText = "SELECT Count(*) FROM logins WHERE username = @user AND password = @pass"; 
      cmd.Parameters.AddWithValue("@user", username); 
      cmd.Parameters.AddWithValue("@pass", password); 

      int count = int.Parse(cmd.ExecuteScalar().ToString()); 
      return count > 0; 
     } 
    } 

tôi đã sử dụng Đồng hồ bấm giờ để điểm chuẩn này phương pháp và truy vấn với một kết nối với ổ khóa được thực hiện trong + - 20ms đó là + - chỉ chậm trễ của mạng nhưng với việc sử dụng nó là + - 55ms vì phương pháp .Open() mất + - 35ms.

Tại sao nhiều người sử dụng phương pháp với việc sử dụng nếu có hiệu suất kém hơn nhiều? Hay tôi đang làm gì sai?

+0

Bạn đã [bật MARS] (https://www.connectionstrings.com/sqlconnection/enable-mars/) và đặt [xử lý không đồng bộ] (https://www.connectionstrings.com/sqlconnection/asynchronous-processing/) trên chuỗi kết nối của bạn? –

+0

@Paulo Morgado Tôi có MySQL không phải SQL. MySQL không có MARS như tôi tìm thấy trên google. –

+1

Thay vì khóa tại sao không mở kết nối khác? – JSteward

Trả lời

8

Bạn nói đúng, mở kết nối là thao tác tốn thời gian. Để giảm thiểu điều này, ADO.NET có kết nối tổng hợp. Kiểm tra this article để biết chi tiết.

Nếu bạn tiếp tục kiểm tra hiệu suất và kiểm tra thời gian cho các kết nối tiếp theo, bạn sẽ thấy thời gian đó cho connection.Open() được cải thiện và nhận được gần 0 ms vì kết nối thực sự được lấy từ Bể bơi.

Với việc triển khai khóa, bạn thực sự sử dụng hồ bơi kết nối chỉ với một kết nối. Trong khi cách tiếp cận này có thể cho thấy hiệu suất tốt hơn trong một thử nghiệm tầm thường, nó sẽ hiển thị kết quả rất kém trong các ứng dụng được tải cao.

+0

tôi sẽ thử kiểm tra nó. –

+1

Ngoài việc này, có lẽ đáng giá thêm việc đề cập đến việc sử dụng ORM, nơi loại công việc này đã được xây dựng cho bạn (xử lý hồ bơi kết nối trong các cá thể ngữ cảnh). – War

+0

Tôi đồng ý, một khóa đơn trong một ứng dụng đồng thời sẽ cho thấy hiệu suất khủng khiếp so với việc sử dụng kết nối ADO.NET. –

Các vấn đề liên quan