2012-02-29 33 views
7

Tôi đã triển khai SqlTransaction trong C# để bắt đầu, giao dịch và quay lại. Mọi thứ đang diễn ra đúng, nhưng tôi đã gặp một số vấn đề trong khi truy cập những bảng có liên quan trong quá trình giao dịch. Tôi không thể đọc bảng trong giao dịch (các bảng đang giao dịch). Trong khi tìm kiếm về điều này, tôi thấy rằng nó xảy ra do một khóa độc quyền. Bất kỳ sự lựa chọn tiếp theo nào trên dữ liệu đó đều phải đợi cho đến khi khóa độc quyền được giải phóng. Sau đó, tôi đã trải qua mọi mức cô lập được cung cấp bởi SqlTransaction, nhưng nó không hoạt động. Vì vậy, tôi cần phải giải phóng khóa độc quyền trong khi giao dịch để người dùng khác có thể truy cập trên bảng đó và có thể đọc dữ liệu. Có phương pháp nào để đạt được điều này không? Cảm ơn trước.Mức cách ly trong Giao dịch Sql

Dưới đây là C# mã của tôi cho giao dịch

try 
{ 
    SqlTransaction transaction = null;       
    using (SqlConnection connection=new SqlConnection(Connection.ConnectionString)) 
    { 
     connection.Open(); 
     transaction=connection.BeginTransaction(IsolationLevel.Snapshot,"FaresheetTransaction");    
     //Here all transaction occurs 
     if (transaction.Connection != null) 
     {  
       transaction.Commit(); 
       transaction.Dispose(); 
     } 
    } 
} 
catch (Exception ex) 
{ 
    if (transaction.Connection != null) 
     transaction.Rollback(); 
    transaction.Dispose(); 
} `       

Mã này đang làm việc tốt, nhưng vấn đề là khi tôi truy cập vào dữ liệu của bảng (những người truy cập trong thời gian giao dịch) trong suốt thời gian thực hiện giao dịch. Các bảng đang được truy cập bởi các phần khác của ứng dụng. Vì vậy, khi tôi cố gắng đọc dữ liệu từ bảng, nó ném một ngoại lệ.

+1

ý định của bạn là gì đây? Không không mất khóa khi cập nhật? hoặc cho những độc giả khác bỏ qua ổ khóa (có lý do chính đáng) –

+1

Tôi không muốn khóa trong bảng đã giao dịch cho người dùng khác .... giao dịch có thể kéo dài trong thời gian giao dịch, mười nghìn dữ liệu chèn vào bảng nên có thể mất nhiều thời gian ... Vì vậy, trong thời gian tran saction, tôi muốn người dùng khác có quyền truy cập vào bảng đó và có thể đọc dữ liệu ....... –

Trả lời

14

Giao dịch SQL, theo thiết kế, ACID. Đặc biệt, đó là "Tôi" đang làm tổn thương bạn ở đây - đây là được thiết kế để ngăn các kết nối khác nhìn thấy trạng thái trung gian không phù hợp.

Kết nối đọc cá nhân có thể chọn để bỏ qua quy tắc này bằng cách sử dụng các NOLOCK gợi ý, hoặc mức READ UNCOMMITTED cô lập, nhưng có vẻ như bạn muốn là cho viết kết nối để không mất nhiều ổ khóa. Vâng, điều đó sẽ không xảy ra.

Tuy nhiên, những gì sức giúp đỡ là cho độc giả sử dụng chụp cô lập, mà đạt được cách ly mà không cần người đọc tham gia khóa (bằng cách nhìn vào, như tên cho thấy, một shapshot point-in-time của nhà nước thống nhất khi giao dịch bắt đầu).

Tuy nhiên, IMO bạn sẽ được tư vấn tốt hơn để nhìn vào một trong hai:

  • nhiều, chi tiết hơn, các giao dịch từ các nhà văn
  • thực hiện công việc trong một bảng dàn (bản sao song song của dữ liệu) , sau đó hợp nhất dữ liệu đó vào dữ liệu thực trong một vài thao tác chèn/cập nhật/xóa hàng loạt, giảm thiểu thời gian giao dịch

Đầu tiên đơn giản hơn.

Thực tế đơn giản là: nếu bạn thực hiện giao dịch dài chạy hoạt động trên nhiều dữ liệu, bạn sẽ gây ra sự cố. Đó là lý do tại sao bạn không làm điều đó. Hệ thống đang hoạt động chính xác.

+2

giải pháp thứ hai của bạn là khá nhiều những gì các snapshot cô lập đang làm cho bạn khi nó được sử dụng cho một giao dịch thực hiện ghi;) – ntziolis

+0

Tôi đã sử dụng mức độ cô lập Snapshot nhưng một lần nữa nó cho cùng một vấn đề ....Trên thực tế nó hoạt động khi tôi sử dụng "select * from tbl_name with (nolock)" nhưng lựa chọn này không phù hợp với tôi vì: 1. Nó đã hiển thị dữ liệu giao dịch chưa được cam kết. 2. bảng đã được truy vấn từ ứng dụng vì vậy nó không phải là khả thi cho tôi để đi qua tất cả các truy vấn trong mã và thay đổi nó ...... –

+1

@ akash88 nó là ** reader ** mà cần phải sử dụng snapshot cô lập; nếu nó không giúp được gì, thì tôi tự hỏi liệu bạn có đơn giản không cho phép cô lập snapshot hay không. Nhưng về cơ bản, bạn đang cố gắng làm điều gì đó chống lại hệ thống. Một ví dụ tương đương có thể là "Tôi có một tệp lớn mở trong khi tôi viết lại các phần lớn của nó; tôi không muốn cho phép truy cập chia sẻ bởi vì sau đó người đọc sẽ thấy các chỉnh sửa đang diễn ra, nhưng không phải tệp bị khóa cho đến khi tôi đóng Làm thế nào để sửa lỗi này? " trả lời: bạn không; bạn thiết kế hệ thống khác nhau. –

3

Cố gắng thực hiện các lần đọc của bạn trong một giao dịch và sử dụng mức cách ly READ UNCOMMITTED. Điều này sẽ ngăn chặn việc đọc không bị khóa, nhưng có thể tạo ra kết quả không hợp lệ:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED  
BEGIN TRANSACTION 

SELECT * FROM Table 

COMMIT TRANSACTION 

Có một quan niệm sai lầm rằng đối phó với các giao dịch/mức cô lập chỉ quan trọng khi viết, trong khi thực tế nó cũng không kém phần quan trọng khi đọc.

+0

Cảm ơn u đã trả lời ..... Tôi đã sử dụng tất cả các loại mức cô lập nhưng nó có thể làm việc với kịch bản của tôi. ..Trên thực tế, tôi đang sử dụng nó trong C# bằng cách sử dụng BeginTransaction() phương pháp của SqlTransaction .... Tôi muốn cung cấp cho truy cập cho người dùng khác cho những bảng được susing trong giao dịch ..... Nhưng, trong mọi mức độ cô lập, độc quyền khóa đang xảy ra ........ –

+0

Nếu bạn đang viết vào bảng, khóa độc quyền là bắt buộc. Ngoại lệ duy nhất là khi bạn sử dụng snapshot mức cô lập, nhưng theo tôi biết điều này chỉ có sẵn bắt đầu từ sql 2008. Vì vậy, cách duy nhất để cho phép đọc là bằng cách sử dụng mức độ cô lập không được đọc hoặc hỗn loạn trong lần đọc như được nêu ở trên – ntziolis

+0

kiểm tra, snapshot cô lập có sẵn trong SQL 2005 đã có, do đó, có bạn đi. Sử dụng chế độ cô lập ảnh chụp khi viết và bạn nên làm tốt. Vì bạn dường như chỉ đọc trong các hoạt động khác nên không có vấn đề gì với điều đó. – ntziolis

2

Sự cố không ở cấp độ viết vào cơ sở dữ liệu mà ở cấp độ giá trị đọc. Bạn đang cố đọc các giá trị đang chèn. Hãy thử thay đổi truy vấn chọn của bạn để theo dõi:

select * from your_table_with_inserts with (nolock) 

tuy nhiên điều này sẽ ghi đè mức độc lập của giao dịch hiện tại và có thể gây đọc bẩn.

Vì vậy, câu hỏi đặt ra là: nếu bạn đang sử dụng giao dịch trên tất cả các truy vấn hoặc chỉ chèn/cập nhật?

1

@ AKASH88, SNAPSHOT mức cô lập là những gì bạn đang tìm kiếm.

Bạn nói rằng ngay cả khi SNAPSHOT nó không hoạt động như dự kiến, khóa độc quyền đang diễn ra, tôi có thể hiểu rằng, tôi đã có cùng một vấn đề.

Đảm bảo bạn không chỉ kích hoạt SNAPSHOT trên các tùy chọn cơ sở dữ liệu, nhưng cũng phải bật READ COMMITTED SNAPSHOT.

enter image description here

Đây là SQL Server 2008, vì vậy nó vẫn còn không chắc chắn nếu câu trả lời này sẽ giúp :(

Trân trọng!