代码之家  ›  专栏  ›  技术社区  ›  mwolfe02

检查SQL Server服务器可用性的最快方法是什么?

  •  3
  • mwolfe02  · 技术社区  · 16 年前

    我有一个MS访问程序在多个地方使用。它连接到MS SQL Server表,但每个位置的服务器名称不同。我正在寻找测试服务器存在性的最快方法。我当前使用的代码如下:

    ShellWait "sc \\" & ServerName & " qdescription MSSQLSERVER > " & Qt(fn)
    FNum = FreeFile()
    Open fn For Input As #FNum
    Line Input #FNum, Result
    Close #FNum
    Kill fn
    
    If InStr(Result, "SUCCESS") Then ...
    

    shellwait:执行shell命令并等待其完成
    qt:用双引号括住字符串
    fn:临时文件名变量

    我根据服务器名称列表(通常只有一个服务器名称)运行上述代码。如果服务器可用,代码大约需要一秒钟,对于每个不可用的服务器,代码大约需要8秒钟。如果可能的话,我想把这两种情况都降低一点,但特别是失败的情况,因为这种情况最常发生。

    6 回复  |  直到 16 年前
        1
  •  2
  •   Heinzi    16 年前

    您可以尝试创建一个ADO连接,并将超时设置为一些较低的值,例如(未测试):

    Dim cn As ADODB.Connection 
    Set cn = New ADODB.Connection
    cn.ConnectionTimeout = 4     ' Wait at most 4 seconds for connection
    cn.ConnectionString = "Provider=SQLOLEDB.1;Data Source=" & ServerName & ";Integrated Security=SSPI"
    
    On Error Resume Next
    cn.Open
    If Err.Number > 0 Then
        ...
    Else
        cn.Close
        ...
    End If
    On Error Goto 0   ' replace 0 with previously used error handler
    
        2
  •  2
  •   dmaruca    16 年前

    我很抱歉,如果我是新来的,我有点不合时宜,但我想提个建议。实际上,您可以在不使用中间文本文件(使用WindowsAPI)的情况下捕获shelled命令的输出。我创建了一个小类文件,它将这个文件包装得很干净。( link )

    使用这个,您可以将代码重构为这个代码,而不必担心读取文件时增加的麻烦。

    Function SQLServerDBExists(ServerName As String, DbName As String) As Boolean
    Dim Result As String
    Dim cls as new clsRunApp
    
    On Error GoTo Err_SQLServerDBExists
    
    'Check for existence of the server
    Result = cls.RunAppWait_CaptureOutput("nslookup " & ServerName)
    If InStr(Result, "Non-existent domain") Then
        SQLServerDBExists = False
        GoTo Exit_SQLServerDBExists
    End If
    
     Result = cls.RunAppWait_CaptureOutput("sc \\" & ServerName & " qdescription MSSQLSERVER")
    If InStr(Result, "SUCCESS") Then
        With PassThru("SELECT Name FROM sysdatabases " & _
                      "WHERE Name='" & DbName & "'", "master", ServerName)
            SQLServerDBExists = (Not .EOF)
        End With
    End If
    
    Exit_SQLServerDBExists:
        Exit Function
    Err_SQLServerDBExists:
        LogError Err.Number, Err.Description, "SQLServerDBExists", "AttachToSQL", , , Erl
        Resume Exit_SQLServerDBExists
    End Function
    
        3
  •  2
  •   mwolfe02    16 年前

    我最终决定采用的解决方案是使用nslookup.exe作为sc.exe命令的前身。如果SQL Server服务器不存在,nslookup会立即通知我。这样做可以将SQL Server查找失败的时间从8秒缩短到1秒以下。成功的案例实际上稍微长一点,但并不明显。对于那些可能感兴趣的人,这里是我的最终解决方案(希望我的个人功能[shellwait、qt、passthrough、logerror]的目的是显而易见的):

    更新:我已经更新了函数,将dmaruca的clsrunapp(我最喜欢的新类模块)和philippe提出的有关在断开连接模式下工作的问题结合在一起。结果比我最初发布的要好得多,我想感谢他们的贡献。现在的功能是:

    Function SQLServerDBExists(ComputerName As String, DbName As String) As Boolean
    Const LocalHost = "127.0.0.1"
    Dim Result As String, RunApp As New clsRunApp
    
        On Error GoTo Err_SQLServerDBExists
    
        If ComputerName <> LocalHost And _
           ComputerName <> "." And _
           ComputerName <> Environ("COMPUTERNAME") Then
            'Check for existence of the server using Name Server Lookup'
            Result = RunApp.RunAppWait_CaptureOutput("nslookup " & ComputerName)
            If InStr(Result, "Non-existent domain") Or _
               InStr(Result, "Default servers are not available") Then
                SQLServerDBExists = False
                GoTo Exit_SQLServerDBExists
            End If
        End If
    
        Result = RunApp.RunAppWait_CaptureOutput("sc \\" & ComputerName & " qdescription MSSQLSERVER")
        If InStr(Result, "SUCCESS") Then
            With PassThru("SELECT Name FROM sysdatabases " & _
                          "WHERE Name='" & DbName & "'", "master", ComputerName)
                SQLServerDBExists = (Not .EOF)
            End With
        End If
    
    Exit_SQLServerDBExists:
        Exit Function
    Err_SQLServerDBExists:
        LogError Err.Number, Err.Description, "SQLServerDBExists", "AttachToSQL"
        Resume Exit_SQLServerDBExists
    End Function
    

    注意:我认识到environ(“computer name”)不是一种100%可靠的确定计算机名称的方法,因此,如果您愿意,可以用您自己的代码替换它。我认为懒惰的方法在这里就足够了。

        4
  •  1
  •   Mitch Wheat    16 年前

    我这样做的方式(在遥远的过去)是使用链接表,并有一个用户表单,允许在运行时一次性选择服务器。或者,您可以将服务器名放在配置文件中,并使用它动态创建连接字符串。

        5
  •  1
  •   David Espart    16 年前
    telnet servername 1433
    
        6
  •  0
  •   Philippe Grondier    16 年前

    这里提出的解决方案在特定条件下非常有效,在这种情况下,计算机是联网的,并且有一个DNS服务器可用。如果您的应用程序应该在连接(您可以连接到其中一个“主”服务器)和断开连接模式(您可以连接到数据库的本地副本)下工作,则此解决方案不会执行此操作。

    我们的通用、高效但(我必须承认)不是那么聪明的解决方案,直到现在才有一个客户端连接表(事实上,XML文件-每个连接一个-在app文件夹中)并允许用户在启动时选择连接。根据用户、他在哪里工作以及他离线工作的能力,我们可以选择在他的计算机上安装哪些XML连接字符串。

    我们的想法是(当我们有时间的时候)使用计算机的IP地址来识别/计算可用的“最佳”数据库服务器:如果计算机没有联网,连接将被设置为“本地主机”。否则,连接将“即时”建立在一个网络上,在该网络中,数据库服务器将被赋予预先限定的IP后缀。因此,当计算机的IP为a a a.bbb.ccc.ddd时,计算机将知道它必须连接到a a a.bbb.120.132,其中120.132是预定义的数据库服务器后缀。