2012-08-24 20 views
7

Medio Ambiente:ADO.Net SqlCommand.ExecuteReader() se ralentiza o se cuelga

Aplicación (escrito en C# para .Net 4) tiene hasta 10 hilos, cada hilo ejecuta en su propio dominio de aplicación. Cada subproceso usa un ADO.Net DataReader que obtiene los resultados del procedimiento almacenado en SQL-Server 2008. También un subproceso puede usar ADO.Net para realizar una operación de escritura (inserción masiva). Todo se ejecuta en la máquina local.

Problema # 1:

Ocasionalmente (aproximadamente cada 30a run) ejecución de un subproceso ralentiza drásticamente. Eso ocurre cuando DataReader obtiene los resultados del procedimiento almacenado: SqlCommand.ExecuteReader(). Por lo general, la operación de lectura se ejecuta en 10 segundos. Cuando se ralentiza, se ejecuta en 10-20 minutos. SQLProfiler muestra que los datos se están consultando, aunque muy lentamente.

pila de llamadas de la desaceleración (tenga en cuenta que no hay excepciones):

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 … 

Problema # 2:

En lugar de una ralentización un hilo puede colgar.

pila de llamadas:

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 fueron adquiridas utilizando herramientas de depuración en el hilo de fondo. No hay excepciones, ya sea una desaceleración o colgando.

SNIReadSync es un mecanismo que funciona a nivel de red y trabaja con la transmisión de paquetes a través de la red. Hemos reproducido este problema en la máquina local, eliminando los problemas de red de la ecuación.

Estamos buscando cualquier entrada y soluciones o soluciones para estas ralentizaciones/cuelgues. Por ahora planeamos detectar la ralentización y volver a ejecutar la operación. Gracias por adelantado.

estoy añadiendo código simplificado para el método conforme a lo solicitado:

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

¿Puede mostrar el código? Especialmente cuando estás creando, abriendo, cerrando la conexión y ejecutando el lector. –

+2

Eso suena más como un problema en el lado db. ¿Hay algún proceso de trabajo en SQL que se ejecute periódicamente? ¿Una Sincronización o alguna acción que está causando un bloqueo de fila/tabla? ¿Qué tan grandes son las tablas involucradas? qué tipo de índices/restricciones, etc. – Brian

+0

@TimSchmelter - He agregado un código que se cuelga. – Cortlendt

Respuesta

1

Debido a que el código funciona perfectamente por un tiempo podemos reducirlo a:

  • bloqueo de base de datos/bloqueo de su procesos y algunos otros.
  • Bloqueo/bloqueo de la base de datos solo de sus procesos.
  • Conectividad de red.
  • Estado de los datos.
  • Espacio en disco u otro problema aparentemente no relacionado en el servidor.

Diría que es probable que sea un problema de bloqueo/bloqueo de la base de datos. Pero realmente necesita determinar esto con certeza. Para hacer esto:

  • Asegúrese de que haya espacio en disco donde las bases de datos están escribiendo, incluidos los registros de la base de datos y cualquier otro registro.
  • Asegúrate de que ningún otro proceso esté usando la base de datos.
  • Preferiblemente utilice una base de datos local para eliminar problemas de red.
  • Está utilizando .Net 4, por lo que si está utilizando tareas, será muy fácil hacer que funcionen de forma sincronizada con las sobrecargas. Haga esto y vea si el problema todavía está allí.

Hacer todo lo anterior debería eliminar los problemas, y puede comenzar a reducirlo aún más desde allí.

3

Hemos estado tratando de depurar un problema similar durante meses, y finalmente lo rastreó hoy ...

Tuvimos una consulta que estaba escondido en la memoria caché (sin calliong ToList/ToArray/etc. en eso). La consulta se vinculó efectivamente a una conexión que se había limpiado desde entonces, y obtuvimos lo que parecía ser 100% de bloqueo de CPU de [código] ReadSni [/ code] (pila completa incluida a continuación).

Sospecho que el código de caché se escribió antes de cambiar la consulta para usar Linq (y se usó para devolver una lista, pero aún se echó como IEumberable) por lo que se introdujo cuando alguien hizo el acceso de datos "flojo".

No puedo explicar por qué solo sucedió cada pocos días en la producción; o bien el almacenamiento en caché no se usa mucho, o la conexión tenía que estar en un cierto estado para que fallara de esta manera.

[code] OS Tema Id: 0x20b8 (27) Niño SP llamada IP del sitio 16edd0fc 6184267e System.Data.SqlClient.TdsParserStateObject.ReadSni (System.Data.Common.DbAsyncResult, System.Data.SqlClient.TdsParserStateObject) 16edd134 61842624 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 61849640 System.Data.SqlClient.SqlInternalConnection.Deactivate() 16edd1b0 61849587 System.Data.ProviderBase.DbConnectionInternal.DeactivateConnection() 16edd1e4 61849405 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 (booleano, NHibernate.ITransaction) 16edd3ec 11acf5de NHibernate.AdoNet.ConnectionManager.AfterNonTransactionalQuery (booleano) 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 [[Sistema. . _Canon, mscorlib]] MoveNext() * ADVERTENCIA: No se puede verificar suma de comprobación para System.Core.ni.dll * ERROR: cargar el módulo completado pero los símbolos no se pueden cargar para 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 [[Sistema .__ Canon, mscorlib]] .. ctor (System.Collections.Generic.IEnumerable`1) * ADVERTENCIA: No se puede para verificar la suma de comprobación para mscorlib.ni.dll * ERROR: Carga del módulo completada pero no se pudieron cargar símbolos para mscorlib.ni.dll

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

+0

¿Pudo resolver el problema? Si es así, ¿era un problema de configuración en el lado del servidor SQL, el lado ADO.NET, o un cambio de código? – cortijon

+1

Un cambio de código. Llamamos a ToList() antes de colocar los elementos en caché, por lo que los elementos reales se almacenaron en caché en lugar de una enumeración aún no evaluada. No creo que lo hayamos visto desde entonces :-) –

0

Yo tenía el mismo problema y lo soluciona después de varias pruebas que hablar de mi caso específico, pero creo podría ser útil.

En mi sistema tengo un complejo motor OLAP en SQLServer 2008. Con los años, las operaciones crecieron en volumen y cantidad y aleatoriamente recibí el error mencionado en la publicación ... operaciones de elevación el error desapareció. Comprobé dos veces el código de todas las operaciones OLAP y todas las transacciones, conexiones y objetos del lector se manejaron perfectamente.

Los puntos críticos que generan errores (pero no siempre) cuando tenía secciones de bucles while para consultar SQL Server, el bombardeo repetido de querys genera errores en el PP

Ho ristrutturato le molte piccole querys in una consulta più grandi (en termini di resultset) ed ho operato delle operazioni attraverso LINQ, il risultato è stato soprendente. Perdormance di 10 volte migliorate e 0 errori.

El consejo que puedo dar es analizar bien las secciones críticas del código, incluso teniendo mucho cuidado al usar Connections, DataReader y Transactions.

Cuestiones relacionadas