2009-04-06 36 views
14

chúng tôi gặp sự cố khi sử dụng TransactionScope. TransactionScope cho phép chúng tôi linh hoạt rất tốt để sử dụng các giao dịch trên Lớp Truy cập Dữ liệu của chúng tôi. Bằng cách này, chúng ta có thể sử dụng các giao dịch ngầm hoặc rõ ràng. Có một số tăng hiệu suất một lần nữa các giao dịch ADO.NET, nhưng tại thời điểm này điều này không thực sự là vấn đề. Tuy nhiên chúng tôi có vấn đề với khóa. Trong mã ví dụ dưới đây, mặc dù mức cô lập được đặt thành ReadCommitted, nhưng không thể tạo câu lệnh Select SQL từ máy khách khác trên bảng testTable, cho đến khi giao dịch chính (trong phương thức chính) sẽ được thực hiện bởi vì có khóa trên toàn bộ bảng. Chúng tôi cũng đã cố gắng chỉ sử dụng một kết nối trên tất cả các phương pháp, nhưng hành vi tương tự. DBMS của chúng tôi là SQL Server 2008. Có điều gì chúng tôi không hiểu không?Cấp độ giao dịch và cách ly

Trân Anton Kalcik

Xem mẫu này mã:

class Program 
{ 
    public class DAL 
    { 
     private const string _connectionString = @"Data Source=localhost\fsdf;Initial Catalog=fasdfsa;Integrated Security=SSPI;"; 

     private const string inserttStr = @"INSERT INTO dbo.testTable (test) VALUES(@test);"; 

     /// <summary> 
     /// Execute command on DBMS. 
     /// </summary> 
     /// <param name="command">Command to execute.</param> 
     private void ExecuteNonQuery(IDbCommand command) 
     { 
      if (command == null) 
       throw new ArgumentNullException("Parameter 'command' can't be null!"); 

      using (IDbConnection connection = new SqlConnection(_connectionString)) 
      { 
       command.Connection = connection; 
       connection.Open(); 
       command.ExecuteNonQuery(); 
      } 
     } 

     public void FirstMethod() 
     { 
      IDbCommand command = new SqlCommand(inserttStr); 
      command.Parameters.Add(new SqlParameter("@test", "Hello1")); 

      using (TransactionScope sc = new TransactionScope(TransactionScopeOption.Required)) 
      { 
       ExecuteNonQuery(command); 
       sc.Complete(); 
      } 
     } 

     public void SecondMethod() 
     { 
      IDbCommand command = new SqlCommand(inserttStr); 
      command.Parameters.Add(new SqlParameter("@test", "Hello2")); 

      using (TransactionScope sc = new TransactionScope(TransactionScopeOption.Required)) 
      { 
       ExecuteNonQuery(command); 
       sc.Complete(); 
      } 
     } 
    } 

    static void Main(string[] args) 
    { 

     DAL dal = new DAL(); 
     TransactionOptions tso = new TransactionOptions(); 
     tso.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted; 

     using (TransactionScope sc = new TransactionScope(TransactionScopeOption.Required,tso)) 
     { 
      dal.FirstMethod(); 
      dal.SecondMethod(); 
      sc.Complete(); 
     } 
    } 
} 

Trả lời

19

Tôi không nghĩ vấn đề của bạn có bất cứ điều gì để làm với các khái niệm NET TransactionScope. Thay vào đó, có vẻ như bạn đang mô tả hành vi dự kiến ​​của các giao dịch SQL Server. Ngoài ra, việc thay đổi mức cách ly chỉ ảnh hưởng đến "đọc dữ liệu" chứ không phải "ghi dữ liệu". Từ Máy chủ SQL BOL:

"Chọn mức cô lập giao dịch không ảnh hưởng đến khóa được bảo vệ để sửa đổi dữ liệu và giữ khóa đó cho đến khi giao dịch hoàn tất, bất kể mức cô lập được đặt cho giao dịch đó. Đối với hoạt động đọc, mức cô lập giao dịch chủ yếu xác định mức độ bảo vệ khỏi ảnh hưởng của các sửa đổi được thực hiện bởi các giao dịch khác. "

Điều đó có nghĩa là bạn có thể ngăn chặn các hành vi ngăn chặn bằng cách thay đổi mức độ cách ly cho khách hàng ban hành SELECT statement (s). Mức cách ly READ COMMITED (mặc định) sẽ không ngăn chặn việc chặn. Để ngăn chặn việc chặn máy khách, bạn sẽ sử dụng mức cách ly READ UNCOMMITTED nhưng bạn phải tính đến khả năng các bản ghi có thể được truy xuất đã được cập nhật/chèn vào bởi một giao dịch mở (tức là chúng có thể biến mất nếu giao dịch quay lại) .

+0

Cảm ơn bạn đã gợi ý. Vì vậy, nếu hiểu đúng, các thiết lập mức cô lập giao dịch tại TransactionScope sẽ chỉ ảnh hưởng đến cách tôi có thể truy cập dữ liệu bằng cách đọc hoạt động trên DBMS từ phạm vi giao dịch này. –

9

Câu hỏi hay để nói về giao dịch.

Phương thức chính của bạn là giữ giao dịch để cam kết. Ngay cả khi bạn cam kết trong các phương pháp khác, bạn vẫn sẽ có khóa trên hàng đó. Bạn sẽ không thể đọc bảng đó với READ COMMITTED, được dự kiến, cho đến khi bạn cam kết giao dịch khóa của mình.

Đây là sau khi trở về phương pháp đầu tiên:

First method returns

Sau khi trở về phương pháp thứ hai, bạn sẽ thêm một khóa để bàn.

secont method returns

Nếu chúng ta thực hiện lựa chọn công bố từ một cửa sổ truy vấn với SPID (55), bạn sẽ thấy tình trạng chờ đợi.

select is waiting

Sau khi bạn phương pháp chính xuyên cam kết, bạn sẽ nhận được kết quả chọn tuyên bố và nó sẽ chỉ hiển thị chia sẻ khóa từ chọn trang truy vấn tuyên bố của chúng tôi.

Scope commits and select returns

X nghĩa khóa độc quyền, IX khóa ý định. You can read more from my blog post about transactions.

Nếu bạn muốn đọc mà không cần đợi, bạn có thể sử dụng gợi ý nolock. Nếu bạn muốn đọc sau khi phương thức đầu tiên cam kết, bạn có thể loại bỏ phạm vi bên ngoài đó.

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