2012-07-02 26 views
54

Tôi chỉ tự hỏi những gì một lý do chính đáng để sử dụng Serializable như là mặc định IsolationLevel có thể khi tạo các System.Transactions TransactionScope, bởi vì tôi không thể nghĩ ra bất kỳ (và có vẻ như là bạn không thể thay đổi mặc định thông qua web/app.config vì vậy bạn luôn phải đặt nó trong mã của bạn)Tại sao System.Transactions TransactionScope mặc định IsolationLevel Serializable

using(var transaction = TransactionScope()) { 
    ... // creates a Transaction with Serializable Level 
} 

thay vào đó tôi luôn phải viết code soạn sẵn như thế này:

var txOptions = new System.Transactions.TransactionOptions(); 
txOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted; 

using(var transaction = new TransactionScope(TransactionScopeOption.Required,txOptions)) { 
    ... // 
} 

Bất kỳ ý tưởng nào?

+1

Di chuyển mã bản mẫu đó vào một phương thức trợ giúp và vấn đề này sẽ không bao giờ làm phiền bạn nữa. – usr

Trả lời

68

Thực tế Serializable là mặc định xuất phát từ thời điểm .NET không được phát hành (trước năm 1999), từ DTC (Distributed Transaction Coordinator) lập trình.

DTC sử dụng một nguồn gốc ISOLATIONLEVEL liệt kê:

ISOLATIONLEVEL_SERIALIZABLE dữ liệu đọc bởi một giao dịch hiện tại không có thể được thay đổi bằng cách giao dịch khác cho đến khi các giao dịch vãng lai kết thúc. Không có dữ liệu mới có thể được chèn vào sẽ ảnh hưởng đến giao dịch hiện tại. Đây là mức cách ly an toàn nhất và là mặc định, nhưng cho phép mức đồng thời thấp nhất.

.NET TransactionScope được xây dựng dựa trên những công nghệ này.

Bây giờ, câu hỏi tiếp theo là: tại sao DTC định nghĩa ISOLATIONLEVEL_SERIALIZABLE làm cấp giao dịch mặc định? Tôi cho rằng đó là vì DTC được thiết kế vào khoảng năm 1995 (trước năm 1999 chắc chắn). Vào thời điểm đó, SQL Standard là SQL-92 (hoặc SQL2).

Và đây là những gì SQL-92 nói về mức độ giao dịch:

Một SQL giao dịch có mức độ cách ly được đọc không bị giam, ĐỌC CAM, đọc lặp lại, hoặc SERIALIZABLE. Mức cô lập của giao dịch SQL xác định mức độ hoạt động trên Dữ liệu SQL hoặc lược đồ trong giao dịch SQL đó bị ảnh hưởng bởi hiệu ứng và có thể ảnh hưởng đến hoạt động trên dữ liệu SQL hoặc lược đồ trong đồng thời Các giao dịch SQL. Mức cô lập của giao dịch SQL là SERIALIZABLE theo mặc định. Mức có thể được đặt rõ ràng theo số <set transaction statement>.

Việc thực thi các giao dịch SQL đồng thời ở mức cô lập SERIALIZABLE được đảm bảo có thể tuần tự hóa được. Một chuỗi có thể tuần tự hóa exe- được định nghĩa là việc thực thi các hoạt động của concur- thực thi các giao dịch SQL có hiệu quả giống như một số thực thi nối tiếp cùng các giao dịch SQL đó. Một chuỗi exe- là một trong đó mỗi giao dịch SQL thực thi để hoàn thành trước khi giao dịch SQL tiếp theo bắt đầu.

+2

Cảm ơn câu trả lời rất thú vị và thông tin này. –

25

Vâng, tôi đoán đây là một trong những "chỉ người thiết kế chắc chắn sẽ biết" loại câu hỏi. Nhưng đây là hai xu của tôi bằng cách nào đó:

Trong khi Serializable là mức cô lập "giới hạn" nhất (liên quan đến khóa, trong RDBMS dựa trên khóa và do đó truy cập đồng thời, deadlocks, v.v.) "mức cô lập (liên quan đến tính nhất quán của dữ liệu).

Vì vậy, trong khi yêu cầu thêm công việc trong các trường hợp như của bạn (đã thực hiện điều đó ;-), bạn nên chọn biến thể an toàn nhất theo mặc định. SQL Server (T/SQL) chọn sử dụng READ COMMITTED, rõ ràng là áp dụng các lý do khác :-)

Làm cho nó có thể thay đổi theo cấu hình, sau đó sẽ là một ý tưởng tồi bị hỏng (vì nó có thể không được thiết kế để làm việc với bất kỳ thứ gì khác). Hoặc để biến đối số xung quanh, bằng cách "hardcoding" mức cô lập, bạn có thể đảm bảo rằng ứng dụng của bạn hoạt động như mong đợi. Có thể cho rằng, mức cô lập không phù hợp với tùy chọn cấu hình (trong khi thực tế là transaction timeout).

+2

"bạn có thể hiển thị ứng dụng hoạt động hoàn hảo cho ứng dụng bị hỏng" +1 – Steven

+2

Lưu ý rằng ngay cả mức cô lập có thể tuần tự hóa vẫn không đảm bảo rằng không có vấn đề về tiền tệ nào có thể xảy ra. – Steven

+1

@Steven: Thật vậy. Do đó tôi sử dụng từ ngữ "_most_ safe" ;-) –

40

Một cách hữu ích để cắt giảm viết code soạn sẵn là để bọc nó trong một lớp học xây dựng như sau:

public static class TransactionScopeBuilder 
    { 
    /// <summary> 
    /// Creates a transactionscope with ReadCommitted Isolation, the same level as sql server 
    /// </summary> 
    /// <returns>A transaction scope</returns> 
    public static TransactionScope CreateReadCommitted() 
    { 
     var options = new TransactionOptions 
      { 
       IsolationLevel = IsolationLevel.ReadCommitted, 
       Timeout = TransactionManager.DefaultTimeout 
      }; 

     return new TransactionScope(TransactionScopeOption.Required, options); 
    } 
} 

Sau đó, bạn có thể sử dụng nó như thế này khi tạo ra một phạm vi giao dịch:

using (var scope = TransactionScopeBuilder.CreateReadCommitted()) 
    { 
     //do work here 
    } 

Bạn có thể thêm các phạm vi giao dịch phổ biến khác mặc định vào lớp trình xây dựng khi bạn cần chúng.

+1

đây thực sự là điều tương tự tôi đã làm để có một vị trí trung tâm, nơi để có được "mặc định" Transactionscope cho usecases của tôi –

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