SQL Server 2008 R2连接有时会失败,导致“不正确的login”

作为我们的testing套件的一部分,在unit testing的旁边,模拟一切,不需要数据库连接,我们也有需要数据库的集成testing。

集成testing是必需的,因为我们正在处理大量的遗留代码,并为我们提供了执行高级testing的可能性。

设置

数据库是一个SQL Server 2008 R2,运行在Windows Server 2008 R2系统上,具有所有最新的Windows更新。 对于操作系统和SQL Server都是如此。

运行数据库服务器的虚拟机是我们构build基础架构的一部分,并且是基于每天早上6点的图像而新创build的,并在晚上10点销毁。 所以我知道SQL Server代理和服务本质上是新的,并且每天都在开始。 第一次构build发生在7AM,这使机器有足够的时间来启动和加载所有的服务。

数据库服务器configuration为允许无限数量的连接,并启用命名pipe道和TCP连接。

sa数据库的连接由sa用户进行。

我们对生产数据库a.mdf进行了缩减 ,该数据库包含了执行testing所需的所有表,视图,存储过程和最小数据集。

当集成testing运行时,testing设置将a.mdf作为b.mdf复制到SQL Server安装的DATA文件夹中。 然后使用以下命令将b.mdf附加到数据库:

CREATE DATABASE Foo ON (FILENAME = N'Path\To\b.mdf') FOR ATTACH 

testing运行,执行数据库操作,在testing夹具的拆卸testing中,数据库被分离,b.mdf文件被删除。

以下两个命令分别执行分离:

 ALTER DATABASE Foo SET SINGLE_USER WITH ROLLBACK IMMEDIATE EXEC master.dbo.sp_detach_db @dbname = N'Foo' 

所以,在实践中,我有一套testing装置,具有以下布局:

 Setup(); Test_1(); Test_2(); Test_3(); TearDown(); 

每个安装程序创build一个新的数据库,运行所有的testing,并删除数据库,以便下一个文本夹具开始一个干净,新的数据库。

总共有大约50个文本夹具,每个包含10个testing。 所以这是数据库连接和分离的50倍,并且运行了大约500次testing。

问题

最近几周,我看到与集成testing相关的失败构build数量增加。 我知道我的testing是可以的,因为整个设置在我的本地机器和其他开发人员的机器上完美地工作。 这只是构build服务器报告问题:

 SetUp Error : Namespace.Class.Method SetUp : System.Data.SqlClient.SqlException : Cannot open database "Foo" requested by the login. The login failed. Login failed for user 'sa'. 

很显然,我谷歌search,是的,login是正确的。 我知道,因为它不总是相同的testing失败。 如果我运行整个testing套件10次,它将失败8个,但每次报告失败的testing都是不同的。 错误信息是相同的,说它不能login,有时它也报告没有进程在pipe道的另一端

我也检查,命名pipe道和TCP连接启用,我检查了允许的连接数,…我检查了ERRORLOG文件,但它不包含任何直接关系到我的数据库。

我的猜测是,由于一些奇怪的原因,它发生的速度很快,或者放缓,它不能正确附加或分离数据库,或者是SINGLE_USER调用导致问题。 从我所收集到的信息来看,如果一个testing因login失败,b.mdf文件就不能被删除,因为这个文件似乎正在被使用。

所以我的问题是:还有什么我可以尝试? 是否有错误日志文件或特定的消息,可以提供更多的见解? 有什么我可以做的检查附加和分离是否成功? (可能失败的分离导致login问题?)分离操作是否是asynchronous的,因此在下次调用时它可能还没有完成?

第一个问题:login失败的错误。
testing运行时,您的数据库很可能尚未完全初始化。
你应该在你的程序中看到这个,一个简单的方法就是查询master数据库来查看目标数据库是否启动并运行。

 IF (select name from sys.databases where name = 'foo' and state_desc = 'ONLINE' and is_in_standby = '0') IS NOT NULL PRINT 'database not found'; 

第二个问题:在pipe道的另一端没有进程。
如果您不通过TCP / IP连接,实际上在这背后的错误往往是模糊的。
你可以尝试启用直接的IP连接,或者你可以专注于其他的错误,这可能是造成这种错误的原因。