2010-03-02 42 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); 
相關問題