【问题标题】:Connecting to SQL Server fails in autostart service, works when starting manually. SQL Server not ready, yet service is started在自动启动服务中连接到 SQL Server 失败,在手动启动时工作。 SQL Server 未准备好,但服务已启动
【发布时间】:2014-01-02 20:54:22
【问题描述】:

TL;DR - MSSQL 服务声称已准备好(状态 = 已启动),但尚未真正准备好(请参阅下面的删除文本)

我有 C# 编写的 Windows 服务,它自己安装为 ServiceAccount.LocalSystem 并在 ServicesDependedOn 中指定 MSSQLSERVER

现在我创建了 MS SQL 用户,授予它所有必要的权限和角色(包括所需数据库上的db_owner,以及连接/登录权限)。

当手动运行服务时(通过net startservices.msc 管理器),它可以正常工作,即它连接到数据库。 当我重启机器时,服务抛出这个异常:

Cannot open database "xxxx" requested by the login. The login failed.
Login failed for user 'xxxxx'.

我的哪些配置不正确?同样,当我手动运行服务时,它工作正常!! 我还尝试通过 MS SQL Management Studio 使用此帐户登录 - 这也有效。


按照 cmets 中的建议,我尝试在尝试连接之前等待 - 20 秒睡眠不能解决问题。我正在将 MSSQLSERVER 服务的状态(通过 ServiceController 检查)添加到日志中,并且它是“正在运行”。一切似乎都很好,除了自动启动服务时登录失败

好的,我已经追踪了几个小时。 这是我发现的:

SQL Server 服务 (MSSQLSERVER) 声称准备就绪(状态 = 已启动)很快(发出“net start”命令后大约 2-3 秒)。不幸的是,预热(启动数据库、恢复和其他一些事情)发生在稍后,并且最多需要 2 分钟(120 秒!!)。当然,它会在预热之前拒绝连接。

我已经完成了

try 
{
    connect;
} catch {
    RequestAdditionalTime(); // to avoid Windows Service timeout
    Sleep();
}

while 循环中。

我讨厌这种解决方案,但找不到更清洁的方法。

如果有人知道如何正确操作,请回答。

【问题讨论】:

  • SQL Server 可能需要一段时间才能启动并准备好所有数据库以供操作。它需要创建tempdb并在所有数据库上运行重启恢复。
  • @MartinSmith 有什么方法可以知道它是否已经准备好了?我想避免使用 Thread.Sleep,因为这是相当肮脏的 hack
  • 您可以使用此解决方案来检测服务是否准备好:stackoverflow.com/questions/178147/…
  • @yasso 我不认为这是解决方案,我的服务依赖于 MS SQL,所以它应该在 MS SQL 声称准备好之后运行。问题似乎是 MS SQL 声称已经准备好,但它还没有真正准备好......
  • 在您的编辑之后,我也倾向于看看它在这 2 分钟内做了什么,以及是否可以改进。例如您的tempdb 数据文件是否很大而未启用即时文件初始化?是否有任何数据库的 VLF 过多?

标签: c# sql sql-server


【解决方案1】:

对我有用的唯一解决方案是不中继服务状态,只需每约 10 秒重试一次以连接到服务器。

【讨论】:

    【解决方案2】:

    可以使用上面的方式连接master,调用如下

    select state, databases.state_desc ,* from sys.databases
    
    
    /*
    0 = ONLINE
    1 = RESTORING
    2 = RECOVERING
    SQL Server 2008 through SQL Server 2014
    3 = RECOVERY_PENDING
    SQL Server 2008 through SQL Server 2014
    4 = SUSPECT
    5 = EMERGENCY
    SQL Server 2008 through SQL Server 2014
    6 = OFFLINE
    SQL Server 2008 through SQL Server 2014
    7 = COPYING
    Azure SQL Database
    10 = OFFLINE_SECONDARY
    Azure SQL Database
    */

    或者另一种方法是调用以下检查非 NULL 值,请注意,除非数据库完全准备好,否则这应该返回 NULL。

    SELECT DATABASEPROPERTYEX('MyDatabaseName', 'Collat​​ion')

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-26
      • 2012-10-31
      • 2023-03-22
      • 2014-10-16
      • 1970-01-01
      相关资源
      最近更新 更多