首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何停止Server的用户实例?(Sql用户实例数据库文件已锁定,即使在停止Sql服务之后)

如何停止Server的用户实例?(Sql用户实例数据库文件已锁定,即使在停止Sql服务之后)
EN

Stack Overflow用户
提问于 2010-03-02 23:22:50
回答 3查看 8.2K关注 0票数 6

当使用2005的用户实例特性时,其连接字符串如下:

代码语言:javascript
复制
<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服务也应该停止所有的用户实例,这应该会释放这些文件上的锁。但情况似乎并非如此--是否有人能说明如何停止用户实例,从而使其数据库文件不再被锁定?

更新

好了,我不再懒散了,并且激发了。锁是由sqlserver.exe持有的,但是有两个sql server实例:

代码语言:javascript
复制
sqlserver.exe  PID: 4680  User Name: DefaultAppPool
sqlserver.exe  PID: 4644  User Name: NETWORK SERVICE

该文件由sqlserver.exe实例以PID: 4680打开。

停止"SQL Server (SQLEXPRESS)“服务,用PID: 4644终止进程,而只保留PID: 4680。

考虑到剩余进程的所有者是DefaultAppPool,接下来我尝试的是停止IIS (这个数据库是从一个ASP.Net应用程序中使用的)。不幸的是,这也没有扼杀这一过程。

手动删除其余的sql server进程确实会删除数据库文件上打开的文件句柄,从而允许复制/移动这些文件。

不幸的是,我希望在WiX安装程序的一些安装前/后任务中复制/还原这些文件--因此,我希望有一种方法可以通过停止一个windows服务来实现这一点,而不是不得不执行sqlserver.exe的所有实例,因为这会带来一些问题:

  1. 杀死所有sqlserver.exe实例可能会给计算机上的其他Server实例的用户带来不良后果。
  2. 我不能轻松地重新启动这些实例。
  3. 在安装程序中引入额外的复杂性。

是否有人对如何关闭与特定用户实例关联的sql服务器实例有进一步的想法?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-03-08 17:01:49

使用“Server实用程序”(SSEUtil.exe)或命令来分离SSEUtil使用的数据库。

Server实用程序,SSEUtil是一个可以让您轻松地与Server、http://www.microsoft.com/downloads/details.aspx?FamilyID=fa87e828-173f-472e-a85c-27ed01cf6b02&DisplayLang=en交互的工具

此外,在最后一个连接关闭后停止服务的默认超时时间是一个小时。在开发框中,您可能希望将此更改为5分钟(最低允许时间)。

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

代码语言:javascript
复制
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刷新器,下面的命令用于分离数据库。

代码语言:javascript
复制
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);
票数 7
EN

Stack Overflow用户

发布于 2010-03-08 13:56:38

在单元测试中,我一直在使用下面的帮助方法来分离附在Server上的MDF文件(这样SQ Server就可以释放MDF和LDF文件上的锁,单元测试可以在其自身之后清理).

代码语言:javascript
复制
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 )。
  • “神奇成分”是对系统存储过程db (Transact-SQL)的调用。
  • 我的连接字符串包含"AttachDBFilename“,但没有包含”用户Instance=True",因此此解决方案可能不适用于您的场景
票数 2
EN

Stack Overflow用户

发布于 2010-09-16 22:27:20

我还不能发表评论,因为我还没有足够高的代表。有人能把这个信息转移到另一个答案吗?这样我们就不会被骗了?

我只是用这个帖子来解决我的WIX卸载问题。我用了AMissico回答的这句话。

代码语言:javascript
复制
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,然后把数据库恢复到了网上。如果没有,WIX将在卸载后留下mdf文件。一旦我把数据库恢复在线,WIX就会正确地删除mdf文件。

这是我修改过的线路。

代码语言:javascript
复制
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 );
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2367688

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档