排查 SQL Server 连接问题的建议先决条件和清单

适用范围:SQL Server
原始 KB 数: 4009936

若要有效地排查连接问题,请收集以下信息:

  • 错误消息的文本和错误代码。 检查错误是间歇性的(仅有时发生)还是一致(一直发生)。

  • SQL Server 和客户端系统中的应用程序和系统事件日志。 这些日志有助于检查 SQL Server 上是否存在系统范围问题。

  • 如果连接从应用程序失败,请从应用程序收集连接字符串。 这些字符串通常位于 ASP.NET 应用程序的 Web.config 文件中。

  • 收集并查看 SQL Server 错误日志,了解其他错误消息和异常。

  • 如果具有对 SQL Server 计算机的管理员访问权限,请使用以下过程收集和查看当前计算机设置和服务帐户:

    1. 下载最新版本的 SQLCHECK

    2. 将下载的文件解压缩到文件夹,例如 C:\Temp

    3. 以管理员身份运行命令提示符以收集数据并保存到文件。 例如:SQLCHECK > C:\Temp\server01.SQLCHECK.TXT

    注意

    如果要排查远程客户端的连接问题或对链接服务器查询进行故障排除,请在所涉及的所有系统上运行 SQLCHECK 工具。

排查连接问题的快速清单

注意

以下部分可帮助你快速检查连接问题。 查看各个主题,了解详细的故障排除步骤。

选项 1

如果有权访问“建议的先决条件”部分中提到的 SQLCHECK 工具的输出,并查看输出文件(计算机、客户端安全和 SQL Server)各部分中的信息,请使用这些信息来解决导致问题的问题。 请看以下示例:

文件中的节 要搜索的文本 潜在操作 可以帮助进行故障排除(示例)
计算机信息 警告:网络驱动程序可能已过期 联机检查是否有新驱动程序。 各种连接错误
客户端安全和驱动程序信息 已启用 Diffie-Hellman 密码套件。 如果算法版本在客户端和服务器之间不同,则可能出现间歇性 TLS 故障的风险 如果出现间歇性连接问题,请参阅 应用程序在连接到 Windows 中的 SQL Server 时强行关闭 TLS 连接错误。 远程主机强制关闭现有连接
客户端安全和驱动程序信息 SQL 别名 如果存在,请确保正确配置别名,并指向正确的服务器和 IP 地址。 建立与 SQL Server 的连接时发生与网络相关或特定于实例的错误
SQL Server 信息 感兴趣的服务 如果未启动 SQL 服务,请启动它。 如果在连接到命名实例时遇到问题,请确保 SQL Server Browser 服务已启动或尝试重启浏览器服务。 建立与 SQL Server 的连接时发生与网络相关或特定于实例的错误
SQL Server 信息 域服务帐户属性 如果从 SQL Server 配置链接服务器并将 Del 值信任设置为 false,则可能会遇到链接服务器查询的身份验证问题。 排查“用户登录失败”错误
SQL Server 信息 SPN 不存在 检查此表,查看 SQL Server 的 SPN 是否已正确配置并修复标识的任何问题。 无法生成 SSPI 上下文
SQL Server 信息 SQL Server 实例的详细信息 检查“已启用 TCP”、“TCP 端口”等的值。 查看是否在服务器端启用 TCP/IP,以及 SQL 默认实例是否侦听 1433 或其他端口。 各种连接错误

方法 2

如果无法在 SQL Server 计算机上运行 SQLCHECK,可以在进行深入故障排除之前检查以下项:

  1. 请确保 SQL Server 已启动,并在 SQL Server 错误日志中看到以下消息:

    SQL Server 已做好进行客户端连接的准备。 这只是一条信息性消息,不需要用户执行任何操作。

    在 PowerShell 中使用以下命令检查系统上 SQL Server 服务的状态:

    Get-Service | Where {$_.status -eq 'running' -and $_.DisplayName -match "sql server*"}
    

    使用以下命令搜索特定字符串的错误日志文件“SQL Server 现已准备好进行客户端连接。 这是一条信息性消息;无需执行任何用户操作。”:

    Get-ChildItem -Path "c:\program files\microsoft sql server\mssql*" -Recurse -Include Errorlog |select-string "SQL Server is now ready for client connections."
    
  2. 验证通过 IP 地址建立的基本连接并检查是否存在任何异常: ping -a <SQL Server machine>, ping -a <SQL Server IP address> 如果发现任何问题,请与网络管理员合作。 或者,可以在 PowerShell 中使用 Test-NetConnection

    $servername = "DestinationServer"
    Test-NetConnection -ComputerName $servername
    
  3. 通过查看错误日志检查 SQL Server 是否侦听适当的协议:

     Get-ChildItem -Path "c:\program files\microsoft sql server\mssql*" -Recurse -Include Errorlog |select-string "Server is listening on" , "ready to accept connection on" -AllMatches
    
  4. 检查是否能够使用 UDL 文件连接到 SQL Server。 如果有效,则连接字符串可能存在问题。 有关 UDL 测试过程的说明,请参阅 使用 UDL 文件测试 OLE DB 与 SQL Server 的连接。 或者,可以使用以下脚本创建和启动 UDL-Test.udl 文件(存储在 %TEMP% 文件夹中):

    clear
    
    $ServerName = "(local)"
    $UDL_String = "[oledb]`r`n; Everything after this line is an OLE DB initstring`r`nProvider=MSOLEDBSQL.1;Integrated Security=SSPI;Persist Security Info=False;User ID=`"`";Initial Catalog=`"`";Data Source=" + $ServerName + ";Initial File Name=`"`";Server SPN=`"`";Authentication=`"`";Access Token=`"`""
    
    Set-Content -Path ($env:temp + "\UDL-Test.udl") -Value $UDL_String -Encoding Unicode
    
    #open the UDL
    Invoke-Expression ($env:temp + "\UDL-Test.udl")
    
  5. 检查是否可以从其他客户端系统和不同的用户登录名连接到 SQL Server。 如果能够,问题可能特定于遇到问题的客户端或登录名。 检查有问题的客户端上的 Windows 事件日志以获取更多指针。 此外,请检查网络驱动程序是否是最新的。

  6. 如果遇到登录失败,请确保存在登录名(服务器主体),并且它有权 CONNECT SQL 访问 SQL Server。 此外,请确保分配给登录名的默认数据库正确,并且映射的数据库主体对数据库具有 CONNECT 权限。 有关如何向数据库主体授予 CONNECT 权限的详细信息,请参阅 GRANT 数据库权限。 有关如何向服务器主体授予 CONNECT SQL 权限的详细信息,请参阅 GRANT 服务器权限。 使用以下脚本来帮助你识别这些权限:

    clear
    ## replace these variables with the login, user, database and server 
    $server_principal = "CONTOSO\JaneK"  
    $database_principal = "JaneK"
    $database_name = "mydb"
    $server_name = "myserver"
    
    Write-Host "`n******* Server Principal (login) permissions *******`n`n"
    sqlcmd -E -S $server_name -Q ("set nocount on; SELECT convert(varchar(32),pr.type_desc) as login_type, convert(varchar(32), pr.name) as login_name, is_disabled,
      convert(varchar(32), isnull (pe.state_desc, 'No permission statements')) AS state_desc, 
      convert(varchar(32), isnull (pe.permission_name, 'No permission statements')) AS permission_name,
      convert(varchar(32), default_database_name) as default_db_name
      FROM sys.server_principals AS pr
      LEFT OUTER JOIN sys.server_permissions AS pe
        ON pr.principal_id = pe.grantee_principal_id
      WHERE is_fixed_role = 0 -- Remove for SQL Server 2008
      and name = '" + $server_principal + "'")
    
    Write-Host "`n******* Database Principal (user) permissions *******`n`n"
    sqlcmd -E -S $server_name -d $database_name -Q ("set nocount on; SELECT convert(varchar(32),pr.type_desc) as user_type, convert(varchar(32),pr.name) as user_name, 
      convert(varchar(32), isnull (pe.state_desc, 'No permission statements')) AS state_desc, 
      convert(varchar(32), isnull (pe.permission_name, 'No permission statements')) AS permission_name 
      FROM sys.database_principals AS pr
      LEFT OUTER JOIN sys.database_permissions AS pe
        ON pr.principal_id = pe.grantee_principal_id
      WHERE pr.is_fixed_role = 0
      and name = '" + $database_principal + "'")
    
    Write-Host "`n******* Server to Database Principal mapping ********`n"
    sqlcmd -E -S $server_name -d $database_name -Q ("exec sp_helplogins '" + $server_principal + "'")
    
  7. 如果要排查 Kerberos 相关问题,可以使用“如何”确定身份验证类型是否为 Kerberos 的脚本

常见连接问题

完成先决条件和清单后,请参阅 常见连接问题 ,并选择相应的错误消息以获取详细的故障排除步骤。