2010-08-03 32 views
7

Ứng dụng của chúng tôi (sử dụng NHibernate và ASP.NET MVC), khi đặt trong các thử nghiệm ứng suất sẽ ném rất nhiều lỗi giao dịch NHibernate. Các loại chính là:Xử lý lỗi giao dịch NHibernate

  1. giao dịch không kết nối, hoặc bị ngắt kết
  2. Row đã được cập nhật hoặc xóa bởi giao dịch khác (hoặc bản đồ chưa được lưu giá trị không chính xác)
  3. giao dịch (Process ID 177) đã bế tắc trên khóa tài nguyên với một quá trình khác và đã được chọn làm nạn nhân bế tắc. Chạy lại giao dịch.

Ai đó có thể giúp tôi xác định lý do ngoại lệ 1 không? Tôi biết tôi phải xử lý các ngoại lệ khác trong mã của mình. Ai đó có thể chỉ cho tôi các tài nguyên có thể giúp tôi xử lý các lỗi này một cách hiệu quả không?

Q. Làm cách nào để quản lý Phiên và Giao dịch?

A. Chúng tôi đang sử dụng Autofac. Đối với mỗi yêu cầu máy chủ, chúng tôi tạo vùng chứa yêu cầu mới có phiên trong phạm vi thời lượng của vùng chứa. Khi kích hoạt phiên, chúng tôi bắt đầu giao dịch. Khi yêu cầu hoàn tất, chúng tôi cam kết giao dịch. Trong một số trường hợp, giao dịch có thể rất lớn. Để đơn giản hóa, mọi yêu cầu máy chủ được chứa trong một giao dịch.

+0

Bạn quản lý các phiên và giao dịch như thế nào? –

+0

bạn đã bao giờ tìm thấy một giải pháp cho điều này? –

Trả lời

1

Hãy nhìn vào chủ đề này: http://n2cms.codeplex.com/Thread/View.aspx?ThreadId=85016

Về cơ bản những gì nó nói như một nguyên nhân có thể xảy ra ngoại lệ này:

2010-02-17 21: 01: 41,204 1 WARN NHibernate.Util.ADOExceptio nReporter - System.Data.SqlClient.SqlException: Nhật ký giao dịch cho cơ sở dữ liệu 'databasename' đã đầy. Để tìm hiểu lý do tại sao không gian trong nhật ký không thể được tái sử dụng, thấy cột log_reuse_wait_desc trong sys.databases

Khi kích thước của nhật ký giao dịch là tỷ lệ thuận với khối lượng công việc thực hiện trong giao dịch, có lẽ bạn nên xem xét việc đặt ranh giới giao dịch của bạn qua việc xử lý lệnh 'xử lý' các lệnh trên phần ghi của giao dịch. Sau đó, bạn sẽ có phiên # X, tải trạng thái bạn muốn thay đổi, biến đổi nó và cam kết nó, tất cả là một đơn vị công việc trong #X.

Đối với mặt đọc của mọi thứ, bạn có thể có ISession # Y khác đọc dữ liệu; ISession này có thể được sử dụng để đọc hàng loạt trong ví dụ: RepeatableRead hoặc một cái gì đó tương tự với các tính năng tương lai và chỉ đơn giản có thể được đọc từ một bộ nhớ cache (albiet nó là một chiếc nạng thực sự). Làm theo cách này có thể giúp bạn khôi phục từ "lỗi" không phải; livelocks, deadlocks và giao dịch nạn nhân.

Vấn đề với việc sử dụng giao dịch cho mỗi yêu cầu là ISession của bạn mua lại rất nhiều dữ liệu lưu trữ sách trong khi bạn đang làm việc, tất cả đều là một phần của giao dịch.Do đó cơ sở dữ liệu đánh dấu các dữ liệu (rols, cols, tables, vv) như là một phần trong giao dịch, làm cho biểu đồ chờ đợi trải dài 'các thực thể' (theo nghĩa cơ sở dữ liệu, chứ không phải là DDD). của ranh giới giao dịch của lệnh mà ứng dụng của bạn đã thực hiện.

Để ghi lại (những người khác googling này), Fabio đã có a post đối phó với xử lý ngoại lệ từ lớp dữ liệu. Trích dẫn một số mã của mình;

public class MsSqlExceptionConverterExample : ISQLExceptionConverter 
{ 
    public Exception Convert(AdoExceptionContextInfo exInfo) 
    { 
     var sqle = ADOExceptionHelper.ExtractDbException(exInfo.SqlException) as SqlException; 
     if(sqle != null) 
     { 
      switch (sqle.Number) 
      { 
       case 547: 
        return new ConstraintViolationException(exInfo.Message, 
         sqle.InnerException, exInfo.Sql, null); 
       case 208: 
        return new SQLGrammarException(exInfo.Message, 
         sqle.InnerException, exInfo.Sql); 
       case 3960: 
        return new StaleObjectStateException(exInfo.EntityName, exInfo.EntityId); 
      } 
     } 
     return SQLStateConverter.HandledNonSpecificException(exInfo.SqlException, 
      exInfo.Message, exInfo.Sql); 
    } 
} 
  • 547 là số ngoại lệ cho cuộc xung đột hạn chế.
  • 208 là số ngoại lệ cho tên đối tượng không hợp lệ trong SQL.
  • 3960 là số ngoại lệ cho giao dịch cách ly Snapshot bị hủy do xung đột cập nhật.

Vì vậy, nếu bạn đang gặp phải các vấn đề tương tranh như những gì bạn mô tả; hãy nhớ rằng họ sẽ làm mất hiệu lực ISession của bạn và bạn phải xử lý chúng như trên.

Một phần của những gì bạn có thể đang tìm kiếm là CQRS, nơi bạn có đọc và ghi riêng biệt. Điều này có thể hữu ích: http://abdullin.com/cqrs/, http://cqrsinfo.com.

Vì vậy, để tóm tắt; các vấn đề của bạn có thể liên quan đến cách xử lý các giao dịch của bạn. Ngoài ra, hãy thử chạy select log_wait_reuse_desc from sys.databases where name='MyDBName' và xem những gì nó mang lại cho bạn.

1

Bài nầy có một lời giải thích: http://groups.google.com/group/nhusers/browse_thread/thread/7f5fb68a00829d13

Nói tóm lại, cơ sở dữ liệu có thể cuộn lại giao dịch bằng cách riêng của mình do một số lỗi, do đó khi bạn cố gắng để rollback giao dịch sau đó nó đã được cuộn lại và trong một trạng thái zombie. Điều này có xu hướng che giấu lý do thực sự cho rollback vì tất cả những gì bạn thấy là TransactionException thay vì ngoại lệ thực sự kích hoạt rollback ngay từ đầu.

Tôi không nghĩ có nhiều điều bạn có thể làm về nó ngoài việc đăng nhập và cố gắng tìm ra nguyên nhân gây ra lỗi cơ bản.

0

Tôi biết bài đăng này đã được một thời gian trở lại và giả sử bạn sửa nó, nhưng có vẻ như bạn có vấn đề chia sẻ thread với NHibernate ISession mà không phải là threadsafe. Về cơ bản 1 chủ đề đang bắt đầu một giao dịch và một chủ đề khác đang cố gắng đóng nó lại gây ra tất cả các loại hỗn loạn.