Как остановить пользовательский экземпляр Sql Server? (Файлы базы данных экземпляра пользователя Sql Express заблокированы даже после остановки службы Sql Express)

при использовании функции экземпляра пользователя SQL Server Express 2005 с такой строкой подключения:

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

мы обнаруживаем, что мы не можем скопировать файлы базы данных MyApp.mdf и MyApp_Log.ldf (потому что они заблокированы) даже после остановки службы SqlExpress и должны прибегнуть к настройке службы SqlExpress из автоматического в ручной режим запуска, а затем перезапустить машину, прежде чем мы сможем скопировать файлы.

Это было мое понимание, что остановка Служба SqlExpress также должна остановить все пользовательские экземпляры, что должно освободить блокировки этих файлов. Но это не так - может ли кто - нибудь пролить свет на то, как остановить экземпляр пользователя, чтобы файлы базы данных больше не были заблокированы?


обновление

хорошо, я перестал лениться и запустил Process Explorer. Блокировка была проведена sqlserver.exe-но есть два экземпляра sql server:

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 экземпляры могут иметь нежелательные последствия для пользователей с другими экземплярами Sql Server на своих компьютерах.
  2. я не могу перезапустить тех случаях.
  3. вносит дополнительные сложности в установщик.

есть ли у кого-нибудь дополнительные мысли о том, как завершить работу экземпляров sql server, связанных с конкретным экземпляром пользователя?

4 ответов


используйте " SQL Server Express Utility "(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);

Я использую следующий вспомогательный метод для отсоединения файлов MDF, прикрепленных к SQL Server, в модульных тестах (чтобы сервер SQ освобождал блокировки файлов MDF и LDF, а модульный тест мог очищаться после себя)...

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", но не включали" User Instance=True", поэтому это решение может не применяться к вашему сценарию

Я пока не могу комментировать, потому что у меня еще нет достаточно высокой репутации. Может ли кто-нибудь переместить эту информацию в другой ответ, чтобы у нас не было дурака?

Я просто использовал этот пост для решения моей проблемы удаления WIX. Я использовал эту строку из ответа Амисико.

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.

вот моя измененная строка.

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 );

это может быть не то, что вы ищете, но бесплатный инструмент Unlocker имеет интерфейс командной строки, который может быть запущен из WIX. (Я использовал unlocker некоторое время и нашел его стабильным и очень хорошим в том, что он делает лучше всего, разблокировка файлов.)

Unlocker может разблокировать и переместить/удалить большинство файлов.

недостаток этого приложения, что нужен замок на файл больше не будет. (Но иногда все еще работает просто отлично.) Обратите внимание, что это не убивает процесс, который имеет блокировку. Он просто снимает замок. (Возможно, перезапуска остановленных служб sql будет достаточно для их повторной блокировки и / или правильной работы.)

вы можете получить Unlocker отсюда:http://www.emptyloop.com/unlocker/

чтобы увидеть параметры командной строки run 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:\My App\Data\MyApp.mdf с файлом из вашего установщика, вы хотелось бы что-то вроде unlocker C:\My App\Data\MyApp.mdf -S -D. Это приведет к удалению файла, чтобы вы могли скопировать его в новый.