Como sabemos, problemas de conectividade no SQL Server são normalmente frequentes e dependendo da complexidade do ambiente a identificação da causa pode também ser complexa. No meu caso, hoje pela manhã recebi um alerta dizendo que a conexão via linked server entre dois de meus servidores SQL Server 2005 não estava funcionando.
A primeira coisa que fiz foi verificar o ErrorLog do SQL Server em ambos os servidores para ver se havia alguma mensagem de erro que explicasse a causa do problema. Para minha surpresa tando o log do SQL Server quando o event viewer de ambos os servidores não mostravam nenhuma mensagem de erro para o horário em que o problema começou a ocorrer.
Do servidor origem, resolvi então disparar uma consulta simples (usando o linked server) sobre o banco de dados master do servidor remoto e neste momento recebi a mensagem de erro abaixo:
OLE DB provider “SQLNCLI” for linked server “SQLPRD1” returned message “Login timeout expired”.
OLE DB provider “SQLNCLI” for linked server “SQLPRD1” returned message “An error has occurred while establishing a connection to the server. When connecting to SQL Server 2005, this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections.”.
Msg 53, Level 16, State 1, Line 0
Named Pipes Provider: Could not open a connection to SQL Server [53].
Bom, o que logo me chamou a atenção é o fato da conexão estar sendo estabelecida com o protocolo Named Pipes. Em meus servidores o protocolo Named Pipes são desativados por padrão, com isso, o cliente não vai mesmo conseguir estabelecer uma conexão named pipes. Mas a grande questão era… Por que o SQL Server tentou usar o protocolo named pipes e não o TCPIP?
Fiz algumas pesquisas na .NET e encontrei um artigo bem interessante do blog do time de protocolos do SQL Server (Microsoft SQL Server Protocols Team). O artigo descreve alguns problemas e diz que as causas mais comuns dos problemas de conectividade normalmente estão relacionadas a 5 categorias:
1. String de conexão incorreta, por exemplo, deixando de informar o nome da instância quando usando instância nomeada. Muito comum quando trabalhando com SQL EXPRESS. (não é o meu caso)
2. O protocolo Named Pipes não está ativo no servidor de destino. (no meu caso não é para estar mesmo).
3. Conexão remota não esta ativada. (no meu caso está)
4. O serviço do SQL Server no servidor de destino não está iniciado (esta…sem comentários)
5. Outras rasões, contexto de segurança incorreto (não é o meu caso)
O artigo pode ser lido em http://blogs.msdn.com/sql_protocols/archive/2007/03/31/named-pipes-provider-error-40-could-not-open-a-connection-to-sql-server.aspx
No final do artigo o autor conclui com um checklist bem legal onde deve-se responder as seguintes questões?
1. Is your target server started?
2. Is your target server listening on NP? Which Pipe?
3. Has your client enabled NP? Use the same pipe to connect as Server?
Hummm, isso explicou porque meu servidor de origem estava tentando estabelecer uma conexão Named Pipes e não uma TCPIP. O protocolo NP estava ativo no servidor de origem (ou seja, no cliente). Na ordem de comunicação, este era o segundo protocolo da lista com o qual o SQL Server deveria tentar conectividade, sendo o primeiro o TCPIP. Ou seja, isso me mostrou que meu servidor não estava conseguindo se comunicar com o servidor de destino usando o protocolo TCPIP.
4. Are you making local connection? If so, what is the instance, default or remote?
5. Did you put correct instance name in the connection string? Remember, Sqlexpress is a named instance.
6. Did you enable remote connection? Firewall? IPSec? “File and Printer Sharing” opened? Can access server?
7. Can you make basic connection by using <servername> or <servername><instancename>? Use sqlcmd or osql.
Esta aqui matou o problema. Eu não consegui me conectar no servidor de destino usando o nome do servidor. Estando na console do servidor de origem, ao tentar me conectar usando o utilitário sqlcmd, recebi a mensagem de erro abaixo.
Named Pipes Provider: Could not open a connection to SQL Server [53].
Sqlcmd: Error: Microsoft SQL Native Client : An error has occurred while establishing a connection to the server. When connecting to SQL Server 2005, this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections..
Sqlcmd: Error: Microsoft SQL Native Client : Login timeout expired.
Tentei então fazer uma conexão usando o endereço IP do servidor de destino, e bimba…conectou sem problemas.
Para concluir, um ping no nome do servidor de destino mostrou que o problema era resolução de nome no DNS. Agora advinhe porque o problema ocorreu após algum tempo de utilização normal? Descobri que o servidor de destino estava configurado para obter IP do DHCP (acreditem, esta instalação não foi executada por mim!). Como o servidor pegou um novo IP, o cache do servidor DNS no site de origem ainda não havia sido atualizado. Após configurar o servidor de destino para usar IP fixo e atualizar o DNS em ambos os sites, o processo voltou a funcionar sem problemas.
Um abraço
Nilton Pinheiro