2012-08-24 20 views
7

Môi trường:ADO.Net SQLCommand.ExecuteReader() chậm hoặc treo

ứng dụng (viết bằng C# cho Net 4) có lên đến 10 bài, mỗi thread chạy trong AppDomain riêng của mình. Mỗi thread sử dụng một DataReader ADO.Net có được kết quả từ thủ tục lưu sẵn trên SQL-Server 2008. Ngoài ra một thread có thể sử dụng ADO.Net để thực hiện một hoạt động ghi (Bulk Insert). Mọi thứ đều chạy trên máy cục bộ.

Sự cố # 1:

Thỉnh thoảng (mỗi lần chạy 30 lần) thực hiện một luồng chậm lại đáng kể. Điều đó xảy ra khi DataReader nhận được các kết quả thủ tục lưu sẵn - SqlCommand.ExecuteReader(). Thông thường hoạt động đọc được thực hiện trong 10 giây. Khi nó chậm lại, nó thực hiện trong 10-20 phút. SQLProfiler cho thấy dữ liệu đang được truy vấn, mặc dù rất chậm.

callstack của suy thoái (xin lưu ý rằng không có trường hợp ngoại lệ):

at SNIReadSync(SNI_Conn* , SNI_Packet** , Int32) 
    at SNINativeMethodWrapper.SNIReadSync(SafeHandle pConn, IntPtr& packet, Int32 timeout) 
    at System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult asyncResult, TdsParserStateObject stateObj) 
    at System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket() 
    at System.Data.SqlClient.TdsParserStateObject.ReadBuffer() 
    at System.Data.SqlClient.TdsParserStateObject.ReadByteArray(Byte[] buff, Int32 offset, Int32 len) 
    at System.Data.SqlClient.TdsParserStateObject.ReadString(Int32 length) 
    at System.Data.SqlClient.TdsParser.ReadSqlStringValue(SqlBuffer value, Byte type, Int32 length, Encoding encoding, Boolean isPlp, TdsParserStateObject stateObj) 
    at System.Data.SqlClient.TdsParser.ReadSqlValue(SqlBuffer value, SqlMetaDataPriv md, Int32 length, TdsParserStateObject stateObj) 
    at System.Data.SqlClient.SqlDataReader.ReadColumnData() 
    at System.Data.SqlClient.SqlDataReader.ReadColumnHeader(Int32 i) 
    at System.Data.SqlClient.SqlDataReader.ReadColumn(Int32 i, Boolean setTimeout) 
    at System.Data.SqlClient.SqlDataReader.GetValueInternal(Int32 i) 
    at System.Data.SqlClient.SqlDataReader.GetValue(Int32 i) 
    at System.Data.SqlClient.SqlDataReader.get_Item(String name) 
    at ****.Core.TableDataImporter.ImportDataFromExcel(Int32 tableId, ExcelEntityLocation location, Boolean& updateResult) in … 

Vấn đề # 2:

Thay vì một chậm lại một sợi có thể treo.

callstack:

at SNIReadSync(SNI_Conn* , SNI_Packet** , Int32) 
    at SNINativeMethodWrapper.SNIReadSync(SafeHandle pConn, IntPtr& packet, Int32 timeout) 
    at System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult asyncResult, TdsParserStateObject stateObj) 
    at System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket() 
    at System.Data.SqlClient.TdsParserStateObject.ReadBuffer() 
    at System.Data.SqlClient.TdsParserStateObject.ReadByte() 
    at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) 
    at System.Data.SqlClient.SqlDataReader.ConsumeMetaData() 
    at System.Data.SqlClient.SqlDataReader.get_MetaData() 
    at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) 
    at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) 
    at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) 
    at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) 
    at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) 
    at System.Data.SqlClient.SqlCommand.ExecuteReader() 

Callstacks đã được mua lại sử dụng công cụ gỡ lỗi trong thread nền. Không có trường hợp ngoại lệ nào xảy ra, hoặc chậm lại hoặc treo lên.

SNIReadSync là một cơ chế hoạt động trên cấp độ mạng và hoạt động với việc truyền các gói trên mạng. Chúng tôi đã sao chép vấn đề này trên máy địa phương, loại bỏ các vấn đề về mạng khỏi phương trình.

Chúng tôi đang tìm kiếm bất kỳ đầu vào và giải pháp hoặc cách giải quyết nào cho sự cố chậm/treo này. Bây giờ chúng tôi lập kế hoạch để phát hiện sự chậm lại khi chạy lại thao tác. Cảm ơn trước.

Tôi đang phụ đang đơn giản hóa cho phương pháp theo yêu cầu:

public void ImportDataFromExcel() 
    {    
     try 
     {     
      var _сonnectionBuilk = ... ; // singleton connection (at the app level) 
      var spName = ... ; // stored procedure name 

     var сonnectionToRead = new SqlConnection(connectionStirng); 
     сonnectionToRead.Open(); 

     var sqlCommand = new SqlCommand(spName); 
     sqlCommand.CommandType = CommandType.StoredProcedure; 
     sqlCommand.Parameters.Add(param1Name, SqlDbType.Int).Value = ...; 
     sqlCommand.Parameters.Add(param2Name, SqlDbType.Int).Value = ...; 
     sqlCommand.Parameters.Add(param2Name, SqlDbType.Int).Value = ...; 

     sqlCommand.Connection = сonnectionToRead;    
     sqlCommand.CommandTimeout = timeout; // 120 sec 

     using (var dataReader = sqlCommand.ExecuteReader()) 
     { 
       dataReader.Read(); 
      ..... 
      int pos1 = dataReader.GetOrdinal(columnName1); 
      int pos2 = dataReader.GetOrdinal(columnName2); 
      int pos3 = dataReader.GetOrdinal(columnName3); 
      int pos4 = dataReader.GetOrdinal(columnName4); 
       .....      

      // reading data from sqldatareader 
      int val1 = dataReader.GetInt32(pos1); 
      int val2 = dataReader.GetInt32(pos2); 
      int val3 = dataReader.GetInt32(pos3); 
      var val4 = dataReader.GetDateTime(pos4); 
      ..... 

      // append read data into bulkTable 
      bulkTable.AddCellValue(val1, val2, val3, val4); // bulkTable wraps DataTable, and appends DataRow inside. 

      if(bulkTable.DataTable.Rows > MaxRowsCount) 
      { 
       using (var bulkCopy = new SqlBulkCopy(_сonnectionBuilk)) 
       { 
        bulkCopy.DestinationTableName = _fullTableName; 
        bulkCopy.WriteToServer(bulkTable.DataTable); 
       } 

       var sqlCommandTransfer = new SqlCommand(spName); 
       sqlCommandTransfer.CommandType = CommandType.StoredProcedure; 
       sqlCommandTransfer.Parameters.Add(param1Name, SqlDbType.Int).Value = ...; 
       sqlCommandTransfer.Connection = _сonnectionBuilk; 
       .... 
       sqlCommandTransfer.ExecuteNonQuery(); // transfering data from temp bulk table into original table 
      } 
     } 
    } 
    finally 
    { 
     bulkTable.Dispose(); 
     сonnectionToRead.Close(); 
    } 
} 
+1

Bạn có thể hiển thị mã không? Đặc biệt là nơi bạn đang tạo, mở, đóng kết nối và thực hiện trình đọc. –

+2

Điều đó nghe giống như một vấn đề ở phía bên trái. Có một số quá trình công nhân trên sql chạy định kỳ? Một Đồng bộ hoặc một số hành động gây ra khóa hàng/bảng? Các bảng có liên quan như thế nào? loại chỉ mục/ràng buộc nào, v.v. – Brian

+0

@TimSchmelter - Tôi đã thêm mã bị treo. – Cortlendt

Trả lời

1

Bởi vì mã hoạt động hoàn hảo trong một thời gian chúng ta có thể thu hẹp nó xuống:

  • Cơ sở dữ liệu khóa/chặn từ của bạn quy trình và một số quy trình khác.
  • Khóa/chặn cơ sở dữ liệu chỉ từ các quy trình của bạn.
  • Kết nối mạng.
  • Trạng thái của dữ liệu.
  • Không gian đĩa hoặc một số vấn đề dường như không liên quan khác trên máy chủ.

Tôi muốn nói đây có thể là sự cố về khóa/chặn cơ sở dữ liệu. Nhưng bạn thực sự cần phải xác định điều này cho chắc chắn. Để thực hiện việc này:

  • Đảm bảo có không gian đĩa nơi cơ sở dữ liệu đang ghi - bao gồm nhật ký cơ sở dữ liệu và bất kỳ lần ghi nhật ký nào khác.
  • Đảm bảo không có quy trình nào khác đang sử dụng cơ sở dữ liệu.
  • Tốt hơn nên sử dụng cơ sở dữ liệu cục bộ để loại bỏ các vấn đề về mạng.
  • Bạn đang sử dụng .Net 4 - vì vậy nếu bạn đang sử dụng Công việc thì sẽ rất dễ dàng để chúng chạy đồng bộ với quá tải. Làm điều này và xem vấn đề vẫn còn đó.

Thực hiện tất cả những điều trên sẽ loại bỏ vấn đề - và bạn có thể bắt đầu thu hẹp hơn nữa từ đó.

3

Chúng tôi đã cố gắng để gỡ lỗi một vấn đề tương tự trong nhiều tháng, và cuối cùng theo dõi nó xuống hôm nay ...

Chúng tôi đã có một truy vấn mà đã được cất giấu vào bộ nhớ cache (không calliong ToList/ToArray/etc. trên đó). Truy vấn có hiệu quả gắn liền với một kết nối đã được làm sạch, và chúng tôi đã có những gì dường như là 100% CPU chặn từ [code] ReadSni [/ code] (đầy đủ stack bao gồm dưới đây).

Tôi nghi ngờ mã bộ nhớ đệm đã được viết trước khi truy vấn được thay đổi để sử dụng LINQ (và được sử dụng để trả lại danh sách, nhưng vẫn đóng vai trò là IEumberable) để nó được giới thiệu khi ai đó truy cập dữ liệu "lười".

Tôi không thể giải thích tại sao nó chỉ xảy ra vài ngày một lần trong quá trình sản xuất; hoặc bộ nhớ đệm không được sử dụng nhiều, hoặc kết nối phải ở trong một trạng thái nhất định để nó không hoạt động theo cách này.

[code] OS Chủ đề Id: 0x20b8 (27) Child SP IP Gọi Site 16edd0fc 6184267e System.Data.SqlClient.TdsParserStateObject.ReadSni (System.Data.Common.DbAsyncResult, System.Data.SqlClient.TdsParserStateObject) 16edd134 61.842.624 System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket() 16edd144 618446af System.Data.SqlClient.TdsParserStateObject.ReadBuffer() 16edd150 61c583d0 System.Data.SqlClient.TdsParserStateObject.CleanWire() 16edd15c 61d1beb9 System.Data. SqlClient.TdsParser.Deactivate (Boolean) 16edd174 6184995f System.Data.SqlClient.SqlInternalConnectionTds.InternalDeactivate() 16e dd180 61.849.640 System.Data.SqlClient.SqlInternalConnection.Deactivate() 16edd1b0 61.849.587 System.Data.ProviderBase.DbConnectionInternal.DeactivateConnection() 16edd1e4 61.849.405 System.Data.ProviderBase.DbConnectionPool.DeactivateObject (System.Data.ProviderBase.DbConnectionInternal) 16edd224 61849384 System.Data.ProviderBase.DbConnectionPool.PutObject (System.Data.ProviderBase.DbConnectionInternal, System.Object) 16edd26c 6184920c System.Data.ProviderBase.DbConnectionInternal.CloseConnection (System.Data.Common.DbConnection, System.Data.ProviderBase. DbConnectionFactory) 16edd2ac 618490f7 System.Data.SqlClient.SqlInternalConnection.CloseConnection (System.Data.Common.DbConnection, System.Data.ProviderBase.DbConnectionFactory) 16edd2c4 618393bf System.Data.SqlClient.SqlConnection.Close() 16edd304 11238f0a NHibernate.Connection.ConnectionProvider.CloseConnection (System.Data.IDbConnection) 16edd340 11238eae NHibernate.Connection.DriverConnectionProvider.CloseConnection (System.Data.IDbConnection) 16edd34c 11aceb42 NHibernate.AdoNet.ConnectionManager.CloseConnection() 16edd358 11aceb02 NHibernate .AdoNet.ConnectionManager.AggressiveRelease() 16edd364 11acf783 NHibernate.AdoNet.ConnectionManager.AfterTransaction() 16edd370 11acf6d1 NHibernate.Impl.SessionImpl.AfterTransactionCompletion (Boolean, NHibernate.ITransaction) 16edd3ec 11acf5de NHibernate.AdoNet.ConnectionManager.AfterNonTransactionalQuery (Boolean) 16edd3fc 11acf539 NHibernate.Impl.AbstractSessionImpl.AfterOperation (Boolean) 16edd474 130311e4 NHibe rnate.Impl.SessionImpl.List (NHibernate.IQueryExpression, NHibernate.Engine.QueryParameters, System.Collections.IList) 16ede51c 13031071 NHibernate.Impl.AbstractSessionImpl.List (NHibernate.IQueryExpression, NHibernate.Engine.QueryParameters) 16ede538 13030b68 NHibernate.Impl.ExpressionQueryImpl.List() 16ede568 13030a47 NHibernate.Linq.DefaultQueryProvider.ExecuteQuery (NHibernate.Linq.NhLinqExpression, NHibernate.IQuery, NHibernate.Linq .NhLinqExpression) 16ede59c 11d4c163 NHibernate.Linq.DefaultQueryProvider.Execute (System.Linq.Expressions.Expression) 16ede5b0 11d4c108 NHibernate.Linq.DefaultQueryProvider.Execute [System._ Canon, mscorlib] 16ede5c4 11d4c0a6 Remotion.Linq.QueryableBase 1[[System.__Canon, mscorlib]].GetEnumerator() 16ede5d4 61022108 System.Linq.Enumerable+WhereEnumerableIterator 1 [[Hệ thống. . _Canon, mscorlib]] MoveNext() * Chú ý: Unable to verify checksum cho System.Core.ni.dll * LỖI: tải Mô-đun hoàn thành nhưng các biểu tượng không thể được nạp cho System.Core.ni.dll

16ede5e4 610166ea System.Linq.Buffer 1[[System.__Canon, mscorlib]]..ctor(System.Collections.Generic.IEnumerable 1) 16ede620 6122e171 System.Linq.OrderedEnumerable 1+<GetEnumerator>d__0[[System.__Canon, mscorlib]].MoveNext() 16ede63c 79b39758 System.Collections.Generic.List 1 [[System .__ Canon, mscorlib]] .. ctor (System.Collections.Generic.IEnumerable`1) * Chú ý: Không thể để xác minh tổng kiểm tra cho mscorlib.ni.dll * LRI: Tải mô-đun hoàn thành nhưng không thể tải biểu tượng cho mscorlib.ni.dll

16ede66c 61021acf System.Linq.Enumerable.ToList "> [System .__ Canon, mscorlib] [/ code]

+0

Bạn có thể giải quyết vấn đề này không? Nếu vậy, đó có phải là vấn đề cấu hình ở phía máy chủ SQL, phía ADO.NET hay thay đổi mã không? – cortijon

+1

Thay đổi mã. Chúng tôi gọi ToList() trước khi đưa các mục vào bộ nhớ cache, vì vậy các mục thực tế được lưu trữ thay vì một điều tra chưa được đánh giá. Trong không nghĩ rằng chúng tôi đã nhìn thấy nó kể từ :-) –

0

Tôi đã gặp vấn đề tương tự và tôi đã giải quyết sau vài lần kiểm tra, tôi nói về trường hợp cụ thể của tôi, nhưng tôi nghĩ nó có thể hữu ích.

Trong sistem tôi có một công cụ OLAP phức tạp trên SQLServer 2008. Qua nhiều năm, các hoạt động tăng về khối lượng và số lượng và ngẫu nhiên tôi nhận được lỗi được đề cập trong bài đăng ... Tôi đã kiểm tra lại mã của tất cả các hoạt động OLAP và tất cả các giao dịch, kết nối và các đối tượng trình đọc đã được xử lý một cách hoàn hảo.

Những điểm quan trọng là tạo ra lỗi (nhưng không phải luôn luôn) khi tôi còn phần của vòng lặp while để truy vấn cho SQLServer, vụ đánh bom lặp đi lặp lại của querys tạo ra lỗi trong DB

Hồ ristrutturato le molte piccole querys trong una truy vấn più grandi (trong kết quả cuối cùng) ed ho operato delle operazioni attraverso LINQ, il risultato và stato soprendente. Perdormance di 10 volte migliorate e 0 errori.

Lời khuyên tôi có thể đưa ra là phân tích tốt các phần quan trọng của mã, thậm chí là rất cẩn thận cách bạn sử dụng Kết nối, DataReader và Giao dịch.