2010-03-02 41 views
6

当使用SQL Server Express 2005的用户实例功能与连接字符串是这样的:如何停止Sql Server的用户实例? (SQL Express的用户实例数据库文件被锁定,即使停药后的SQL Express服务)

<add name="Default" connectionString="Data Source=.\SQLExpress; 
    AttachDbFilename=C:\My App\Data\MyApp.mdf; 
    Initial Catalog=MyApp; 
    User Instance=True; 
    MultipleActiveResultSets=true; 
    Trusted_Connection=Yes;" /> 

,我们发现我们不能照搬数据库文件MyApp.mdf和MyApp_Log.ldf(因为它们被锁定),即使在停止SqlExpress服务之后,也必须求助于将SqlExpress服务从自动启动模式设置为手动启动模式,然后重新启动计算机,然后才能复制文件。

这是我的理解,停止SqlExpress服务应该停止所有的用户实例,这应该释放这些文件上的锁。但似乎并非如此 - 任何人都可以阐明如何停止用户实例,以便数据库文件不再被锁定?


更新

OK,我不再是懒惰和发射了进程资源管理器。锁被持有sqlserver.exe - 但也有两个SQL Server实例:

sqlserver.exe PID: 4680 User Name: DefaultAppPool 
sqlserver.exe PID: 4644 User Name: NETWORK SERVICE 

该文件是由sqlserver.exe实例与PID开:4680

停止“SQL服务器(SQLEXPRESS )“服务,使用PID:4644处理了该进程,但是仅保留PID:4680。

作为剩余进程的所有者是DefaultAppPool,接下来我尝试的是停止IIS(从ASP.Net应用程序中使用此数据库)。不幸的是,这并没有消除这个过程。

手动关闭剩余的sql服务器进程并不会删除数据库文件上的打开文件句柄,从而可以复制/移动它们。

不幸的是,我希望在一些WiX安装程序的某些安装前/安装后任务中复制/恢复这些文件,因此我希望可以通过停止Windows服务来实现此目的,而不必掏出杀sqlserver.exe的所有实例为带来了一些问题:

  1. 杀死所有的sqlserver.exe可能对未来有自己的机器上其他的SQL Server实例的用户不良consequencies。
  2. 我无法轻松重新启动这些实例。
  3. 将更多复杂性引入到安装程序中。

有没有人有关于如何关闭与特定用户实例关联的SQL Server实例的任何进一步想法?

+0

想了解所有答案 - 最有用的答案是使用SSEUtil.exe。虽然我们需要从WiX安装程序中调用它,但我们可以发现它会有点问题,即如果运行安装程序的用户没有执行sp_dettach_db的权限,无论使用哪种方法,这都是一个问题 - 因此我们可能只需在升级之前为用户提供一些手动的预安装步骤,以便他们可以使用SSEUtil.exe自行处理。 – Bittercoder 2010-03-14 09:09:14

+0

我很好奇,是不是SSEUtil.exe解决权限问题?如果用户必须使用SSEUtil自己处理,那么安装程序是否应该调用SSEUtil? – AMissico 2010-03-14 17:54:45

+0

在我的测试中,这似乎并不是这种情况 - 我相信这只是因为安装程序在调用SSEUtil时未被提升......但我还没有时间进一步调查它。 在附注上,我们发现SSEUtil不会在安装SqlServer和SqlServer Express的情况下,在Windows7 x64上正确列出所有活动用户实例,即使在传入-s。\ SqlExpress参数时也是如此。 所以我们仍然有一些边缘情况下工作:) – Bittercoder 2010-03-14 21:45:10

回答

7

使用“SQL Server Express的工具”(SSEUtil.exe)或分离SSEUtil使用的数据库的命令。

SQL Server Express的工具, SSEUtil是一个工具,可以让你轻松地与SQL Server进行交互, http://www.microsoft.com/downloads/details.aspx?FamilyID=fa87e828-173f-472e-a85c-27ed01cf6b02&DisplayLang=en

此外,默认的超时停止服务后,最后连接关闭一小时。在您的开发箱中,您可能需要将其更改为五分钟(允许的最小值)。

此外,您可能通过Visual Studio的服务器资源管理器数据连接有开放连接,因此请务必从那里断开与任何数据库的连接。

H:\Tools\SQL Server Express Utility>sseutil -l 
1. master 
2. tempdb 
3. model 
4. msdb 
5. C:\DEV_\APP\VISUAL STUDIO 2008\PROJECTS\MISSICO.LIBRARY.1\CLIENTS\CORE.DATA.C 
LIENT\BIN\DEBUG\CORE.DATA.CLIENT.MDF 

H:\Tools\SQL Server Express Utility>sseutil -d C:\DEV* 
Failed to detach 'C:\DEV_\APP\VISUAL STUDIO 2008\PROJECTS\MISSICO.LIBRARY.1\CLIE 
NTS\CORE.DATA.CLIENT\BIN\DEBUG\CORE.DATA.CLIENT.MDF' 

H:\Tools\SQL Server Express Utility>sseutil -l 
1. master 
2. tempdb 
3. model 
4. msdb 

H:\Tools\SQL Server Express Utility> 

使用.NET Refector,以下命令用于分离数据库。

string.Format("USE master\nIF EXISTS (SELECT * FROM sysdatabases WHERE name = N'{0}')\nBEGIN\n\tALTER DATABASE [{1}] SET OFFLINE WITH ROLLBACK IMMEDIATE\n\tEXEC sp_detach_db [{1}]\nEND", dbName, str); 
+0

谢谢,我需要从许多客户机器上的WiX安装程序调用此操作(谁不会安装SSEUtil),但我会尽可能地探讨此选项。 – Bittercoder 2010-03-08 18:22:47

+1

SSEUtil是.NET应用程序。使用.NET Reflector查看它如何分离数据库。 – AMissico 2010-03-08 18:30:24

+0

我建议将WiX安装程序的要求作为完整问题的一部分。 (你最后一句话)很容易错过这个。 – AMissico 2010-03-08 18:34:47

2

我一直在使用下面的辅助方法,分离连接到SQL Server中的单元测试(这样的MDF和LDF文件和单元测试后本身可以清理SQ Server版本锁)MDF文件...

private static void DetachDatabase(DbProviderFactory dbProviderFactory, string connectionString) 
{ 
    using (var connection = dbProviderFactory.CreateConnection()) 
    { 
     if (connection is SqlConnection) 
     { 
      SqlConnection.ClearAllPools(); 

      // convert the connection string (to connect to 'master' db), extract original database name 
      var sb = dbProviderFactory.CreateConnectionStringBuilder(); 
      sb.ConnectionString = connectionString; 
      sb.Remove("AttachDBFilename"); 
      var databaseName = sb["database"].ToString(); 
      sb["database"] = "master"; 
      connectionString = sb.ToString(); 

      // detach the original database now 
      connection.ConnectionString = connectionString; 
      connection.Open(); 
      using (var cmd = connection.CreateCommand()) 
      { 
       cmd.CommandText = "sp_detach_db"; 
       cmd.CommandType = CommandType.StoredProcedure; 

       var p = cmd.CreateParameter(); 
       p.ParameterName = "@dbname"; 
       p.DbType = DbType.String; 
       p.Value = databaseName; 
       cmd.Parameters.Add(p); 

       p = cmd.CreateParameter(); 
       p.ParameterName = "@skipchecks"; 
       p.DbType = DbType.String; 
       p.Value = "true"; 
       cmd.Parameters.Add(p); 

       p = cmd.CreateParameter(); 
       p.ParameterName = "@keepfulltextindexfile"; 
       p.DbType = DbType.String; 
       p.Value = "false"; 
       cmd.Parameters.Add(p); 

       cmd.ExecuteNonQuery(); 
      } 
     } 
    } 
} 

注:

  • 的SqlConnection。ClearAllPools()对消除“隐形”连接非常有帮助(当连接汇集后,即使您'关闭()'它也会保持活动状态;通过明确清除池连接,您不必担心设置池标志在所有连接字符串中为false)。
  • “魔法成分”是调用系统存储过程sp_detach_db (Transact-SQL)
  • 我的连接字符串包含“AttachDBFilename”,但不包括“用户实例=真”,所以这种解决方案可能并不适用于您的情况
+0

感谢代码 - 在我的情况下,我需要从WiX安装程序(而不是应用程序本身,测试夹具等)调用此 - 也不幸的是数据库用户因为用户实例可能没有足够的权限来调用master上的sp_detach_db。但它确实给了我一些其他的选择来尝试。 – Bittercoder 2010-03-08 18:26:32

+0

以下MSDN文档页面http://msdn.microsoft.com/en-us/library/bb264564(SQL.90).aspx指出:“通过调用sp_detach_db从实例中分离数据库将关闭文件。这是方法Visual Studio用于确保在IDE在用户实例之间切换时数据库文件已关闭。“ - 似乎Visual Studio本身使用sp_detach_db关闭用户实例:-)。我假设@AMissico建议的SSEUtil工具也使用它(它来自Wix的易用的exe文件) – 2010-03-09 03:13:38

+0

我更新了我的答案,以包含SSEUtil使用的实际命令。 – AMissico 2010-03-10 17:26:16

-3

这可能不是您要查找的内容,但免费工具Unlocker具有可从WIX运行的命令行界面。 (我已经使用了一段时间的解锁器,并发现它稳定,非常擅长解锁文件。)

解锁器可以解锁并移动/删除大多数任何文件。

这样做的缺点是需要锁定文件的应用程序将不再拥有它。 (但有时候仍然可以正常工作。)请注意,这不会终止具有锁定的进程。它只是删除它的锁。 (这可能是因为重新启动您停止SQL服务,将足以为它重新锁定和/或正常工作。)

你可以从这里得到解锁:http://www.emptyloop.com/unlocker/

要查看命令行选项运行unlocker -H 在这里,他们是为了方便:

 
Unlocker 1.8.8 

Command line usage: 
    Unlocker.exe Object [Option] 
Object: 
    Complete path including drive to a file or folder 
Options: 
    /H or -H or /? or -?: Display command line usage 
    /S or -S: Unlock object without showing the GUI 
    /L or -L: Object is a text file containing the list of files to unlock 
    /LU or -LU: Similar to /L with a unicode list of files to unlock 
    /O or -O: Outputs Unlocker-Log.txt log file in Unlocker directory 
    /D or -D: Delete file 
    /R Object2 or -R Object2: Rename file, if /L or /LU is set object2 points to a text file containing the new name of files 
    /M Object2 or -M Object2: Move file, if /L or /LU is set object2 points a text file containing the new location of files

假设你的目标是要替换C:\我的应用\ DATA \ MyApp.mdf从您的安装文件,你会希望像unlocker C:\My App\Data\MyApp.mdf -S -D。这会删除文件,以便复制新文件。

+0

嗯,当你得到一个没有评论为什么的投票时就得爱它。 – Vaccano 2010-03-09 16:01:39

+1

我会想象得到的回应是因为如果mdf被锁定,这是一个原因,并且使用解锁器可能会破坏数据库或最糟糕的东西。 – AMissico 2010-03-09 20:34:24

1

我还不能评论,因为我还没有足够的代表。有人可以将这个信息移动到另一个答案,所以我们没有一个愚蠢的?

我刚刚用这个帖子解决了我的WIX卸载问题。我从AMissico的回答中使用了这一行。

string.Format("USE master\nIF EXISTS (SELECT * FROM sysdatabases WHERE name = N'{0}')\nBEGIN\n\tALTER DATABASE [{1}] SET OFFLINE WITH ROLLBACK IMMEDIATE\n\tEXEC sp_detach_db [{1}]\nEND", dbName, str); 

使用WIX时工作得很好,只有我不得不添加一件东西才能使它适用于我。

我已经拿出sp_detach_db,然后将db重新联机。如果你不这样做,WIX会在卸载后离开mdf文件。一旦我将数据库重新联机,WIX会正确删除mdf文件。

这是我修改过的行。

string.Format("USE master\nIF EXISTS (SELECT * FROM sysdatabases WHERE name = N'{0}')\nBEGIN\n\tALTER DATABASE [{0}] SET OFFLINE WITH ROLLBACK IMMEDIATE\n\tALTER DATABASE [{0}] SET ONLINE\nEND", dbName); 
相关问题