none
Erro "Data Reader" RRS feed

  • Pergunta

  • Cenário:

     

    Servidor WEB (novinho) com:

     

    -1GB de RAM (dual channel, non-ecc)

    -2 HD's 250GB em RAID-1

    -Hardware Intel, funcionando 100%

     

    -Windows 2003 Standard R2 SP2;

    -SQL 2005 Atualizado, utilizando apenas UM banco de dados;

    -ASP NET 2.0

    -Localizado numa DMZ, atrás do ISA Server

    -Publicação deste webserver no ISA

     

    Disponibilizei este server para uma empresa de Desenvolvedores, e agora na fase de testes pesados do sistema, questionaram hardware e possíveis problemas na infra.

     

    -No ISA existe uma regra de publicação para encaminhar as requisições da rede externa (internet) para o server, sem nenhuma configuração adicional (SSL, etc).

    -Também existe uma regra de liberação de tráfego HTTP entre a rede interna e a DMZ, para que os usuários da rede interna acessem o site. Não existe regra da DMZ para outras redes. A comunicação é sempre feita do cliente para o servidor, e este retorna os dados para o browser do solicitante.

     

    Vamos aos problemas:

     

    O pool de conexões do SQL está default (se nao me engano, 200), e apenas um usuário rodando uma rotina simples já estoura isso (os desenvolvedores subiram pra 500 e parou o erro, mas mesmo assim achei estranho. Nao sei se é normal abrir inumeras conexoes para um único usuário, imagine se 100 pessoas acessarem o sistema? Provavelmente é cagada no código, mas... ...opinem por favor.)

     

    De fato, o erro crítico é:

     

    "System.InvalidOperationException: Já existe um DataReader aberto associado a este comando que deve ser fechado primeiro."

     

    Este erro ocorre quando um usuário executa 2 ou 3 funções no sistema (é uma grade de horários, pequena.). Só resolve quando reinicio o server ou os serviços. Já li diversos artigos, passei para o pessoal de Dev, mas não resolveram.

     

    Alguém tem alguma idéia do que pode ser isso? Será mesmo que é a infra?

     

    Até.

     

     

    domingo, 9 de dezembro de 2007 22:08

Respostas

  • Oi Hélio,

     

    É difícil afirmar que o Hardware é o problema apenas com o número de usuários. Segundo a metodologia de Tunning da Microsoft, avaliar o desempenho envolve alguns estágios

     

    1. Modelo de dados (Data Schema)
    2. Consultas bem estruturadas (Optimized Queries)
    3. Indexação adequada (Indexing)
    4. Bloqueios bem dimensionados (Locking)
    5. Infra-estrutura adequada (Hardware)

    Esse modelo é avaliado na ordem em que citei (e não o contrário). Para afirmarmos que o Hardware não está adequado, teríamos que revisar todos os outros estágios e apenas com o número de usuários não podemos fazer tal afirmação.

    No entanto, apenas 10 usuários conseguirem provocar tanto processamento assim indica uma coisa. Ou a aplicação é demasiadamente complexa e exige uma grande carga de processamento ou algo está mal estruturado.

     

    1GB é a quantidade mínima de memória recomendada para o SQL Server 2005. Acredito que você terá problemas com essa quantidade quando estiver com 100 usuários. Também não acho muito adequado utilizar o RAID1 para banco de dados. Não que seja ruim, apenas não é muito comum. Outras opções como RAID5, RAID10 ou RAID01 podem ser mais adequadas.

     

    Gostaria de retificar o que disse:

     

    "MARS não irá tornar o processo mais rápido já que ele é uma estrutura para permitir requisições em paralelo".

     

    O MARS não vai tornar o processo mais rápido porque é uma estrutura para permitir o compartilhamento de uma conexão sem bloqueá-la, mas não permite requisições em paralelo.

     

    Fico grato pelo elogio. Estou iniciando no fórum após uma longa pausa... Espero conseguir manter o nível e ajudar os demais colegas com o que eu puder. Se conseguirmos resolver o seu problema ou pelo menos encaminhá-lo gostaria apenas de pedir pra você classificar a resposta.

     

    [ ]s,

     

    Gustavo

     

    segunda-feira, 10 de dezembro de 2007 16:56

Todas as Respostas

  • Bom Dia Hélio,

     

    O SQL Server dispõe de um recurso chamado MARS (Multiple Active ResultSets) que acredito ser muito interessante na resolução do seu problema, mas antes de propriamente falar sobre ele, gostaria de esclarescer algumas questões.

     

    O SQL Server não dispõe de um pool padrão de conexões. Você pode configurar o número máximo de conexões simultâneas que pode ir de 1 até 32.767 conexões. A configuração de um pool de  conexões é algo feito pela aplicação onde na string de conexão você poderá definir se irá utilizar um pool e as quantidades mínima e máxima desse pool. Acredito que tenha sido exatamente isso que os desenvolvedores tenham realizado.

     

    O SQL Server divide sua área de memória em duas partes. A primeira parte é amplamente conhecida e chama-se Buffer Pool. É nessa área que o SQL Server armazena páginas de dados, planos de execução, etc. A outra área chama-se MemToLeave e é destinada a processos internos do SQL Server entre os quais se destacam os Linked Servers e a gerência de conexões. Essa última área possui uma quantidade limitada e por padrão pode chegar no máximo em 256MB (padrão SQL2000). Se muitas conexões forem abertas, essa memória pode ser totalmente consumida e começar a ser um gargalo. M mesmo que haja mais memória disponível, o resto será destinado ao Buffer Pool e não a MemToLeave já que essa é menos flexível.

     

    Imagino que um único usuário utililizar essa quantidade de conexões, deve ser no mínimo para processar múltiplas requisições em paralelo e terminar uma tarefa mais rapidamente. Toda vez que se utiliza um DataReader, a conexão é bloqueada até que esse DataReader não seja mais necessário. Se a cada registro lido pelo DataReader, você tiver que emitir outra instrução (digamos que para cada registro lido, você queira disparar um update), esse Update pode ficar bloqueado (já que a conexão está sendo utilizada pelo DataReader), ou uma conexão em segundo plano pode ser requisitada.

     

    Qualquer um dos comportamentos será ruim, pois, irão impor ou uma demora (update bloqueado) ou uma utilização forte de recursos da MemToLeave (conexões em segundo plano). No caso das conexões em segundo plano, a situação é ainda pior, pois, você terá menos controle sobre elas.

     

    A funcionalidade conhecida como MARS (disponível no SQL Server 2005 através do ADO.NET 2.0), permite que em uma única conexão você tenha múltiplos ResultSets, ou seja, enquanto um conjunto de resultados está sendo lido, você pode fazer outras coisas com a conexão. Não estou dizendo que isso permite processamento em paralelo (certamente o MARS não faz isso). Ele apenas permite que você possa por exemplo iterar um DataReader e disparar comandos Update utilizando a mesma conexão.

     

    O que recomendaria inicialmente é que você adote a utilização do MARS em sua aplicação para efeito de testes e observe os resultados. Verifique também se as conexões são fechadas após serem utilizadas (ainda acho 200 conexões muita coisa para um único usuário). Quanto menos conexões sendo utilizadas, menor será a pressão sobre a MemToLeave e mais memória poderá ser destinada a Buffer Pool para processar consultas mais eficientes e guardar em memória um número maior de dados.

     

    MARS não irá tornar o processo mais rápido já que ele é uma estrutura para permitir requisições em paralelo. Ele apenas tornará mais conexões disponíveis, o que parece ser exatamente o seu problema.

     

    Embora não seja um pré-requisito, para utilizar MARS,é recomendável ter instalado o SQL Native Client no local da sua aplicação e posteriormente mudar suas strings de conexão. A forma como o parâmetro MARS deve ser preenchido varia de tecnologia (SQLCNI, OLEDB, ODBC, etc). Você poderá obter maiores informações sobre MARS no livro "Designing and Optimizing Data Access by Using Microsoft SQL Server 2005".

     

    Espero tê-lo ajudado,

     

    [ ]s,

     

    Gustavo

    segunda-feira, 10 de dezembro de 2007 13:11
  • Gustavo, obrigado pela resposta, foi excelente, mas ainda tenho uma dúvida. Você acha que, conforme informado pela equipe de Dev, o problema é o hardware? Porque imagine, se hoje temos no MÁXIMO 10 usuários usando o software isso já acontece, imagine com 100-200 ? Acho que a máquina aguenta mais que 10 usuários, senão vou ter que comprar um datacenter inteiro !!!

     

    Falha de rede eu acho difícil, pois trata-se de conexões HTTP (tcp 80), portanto há controle no envio e recebimento dos dados, e acho que este erro não ocorreria. O erro ocorre no próprio servidor e o usuário até ve o erro, justamente pela conexao http estar funcionando!!!

     

    QUal sua opinião profissional ? Será a aplicação ?

     

    Vou tentar usar o MARS e te falo.

     

    Obrigado, e na próxima resposta classifico seu post, ok?

     

    Até!

    segunda-feira, 10 de dezembro de 2007 16:15
  • Oi Hélio,

     

    É difícil afirmar que o Hardware é o problema apenas com o número de usuários. Segundo a metodologia de Tunning da Microsoft, avaliar o desempenho envolve alguns estágios

     

    1. Modelo de dados (Data Schema)
    2. Consultas bem estruturadas (Optimized Queries)
    3. Indexação adequada (Indexing)
    4. Bloqueios bem dimensionados (Locking)
    5. Infra-estrutura adequada (Hardware)

    Esse modelo é avaliado na ordem em que citei (e não o contrário). Para afirmarmos que o Hardware não está adequado, teríamos que revisar todos os outros estágios e apenas com o número de usuários não podemos fazer tal afirmação.

    No entanto, apenas 10 usuários conseguirem provocar tanto processamento assim indica uma coisa. Ou a aplicação é demasiadamente complexa e exige uma grande carga de processamento ou algo está mal estruturado.

     

    1GB é a quantidade mínima de memória recomendada para o SQL Server 2005. Acredito que você terá problemas com essa quantidade quando estiver com 100 usuários. Também não acho muito adequado utilizar o RAID1 para banco de dados. Não que seja ruim, apenas não é muito comum. Outras opções como RAID5, RAID10 ou RAID01 podem ser mais adequadas.

     

    Gostaria de retificar o que disse:

     

    "MARS não irá tornar o processo mais rápido já que ele é uma estrutura para permitir requisições em paralelo".

     

    O MARS não vai tornar o processo mais rápido porque é uma estrutura para permitir o compartilhamento de uma conexão sem bloqueá-la, mas não permite requisições em paralelo.

     

    Fico grato pelo elogio. Estou iniciando no fórum após uma longa pausa... Espero conseguir manter o nível e ajudar os demais colegas com o que eu puder. Se conseguirmos resolver o seu problema ou pelo menos encaminhá-lo gostaria apenas de pedir pra você classificar a resposta.

     

    [ ]s,

     

    Gustavo

     

    segunda-feira, 10 de dezembro de 2007 16:56
  • O server está com RAID-1 pois é a primeira máquina disponível para esses testes. Quando entrar em produção, teremos uma máquina separada para o SQL com RAID-5 e um WebFarm para o site.

     

    Abraço!

     

    Obrigado de novo!!!

     

    Hélio Galvão.

    segunda-feira, 10 de dezembro de 2007 17:54
  • Boa Tarde Hélio,

     

    Entendi a questão do RAID-1. É que ele é mais utilizado para o SO e para o Log enquanto que os dados costumam adotar arquiteturas como RAID10 e RAID5 (esse último muito recomendado para bancos com pouca escrita).

     

    No resto mais espero que dê certo a tentativa com o MARS.

     

    [ ]s,

     

    Gustavo

     

    segunda-feira, 10 de dezembro de 2007 18:34
  • Grande Gustavo,

     

    É muito bom saber que temos um grande profissional ativo nos fóruns da Microsoft.

     

    Amigão, estou exatamente com esse problema... tenho que executar um Reader enquanto outro está aberto e estou sendo vetado pelo banco. Eu li sua reposta para o amigo ae e já estou me informando sobre o MARS.

     

    Mas tenho uma pergunta: esse MARS funciona pra qualquer banco gerenciavel pelo ADO.NET ou é somente para o 2005?

     

    Abraços!!!

    Vinicius Vasconcelos

    quinta-feira, 3 de abril de 2008 04:59