2013-11-26 40 views
13

我有一個數據庫21 Gb;其中20 Gb是文件(FileStream),我已經從表中刪除所有文件,但是當我做備份時,備份文件仍然是21 GBDBCC SHRINKFILE的進展

爲了解決這個問題,我成了idee「釋放未使用的空間」。

所以我想收縮我的數據庫如下所示:

USE Db; 
GO 
-- Truncate the log by changing the database recovery model to SIMPLE. 
ALTER DATABASE Db 
SET RECOVERY SIMPLE; 
GO 
-- Shrink the truncated log file to 1 MB. 
DBCC SHRINKFILE (Db, 100); 
GO 
-- Reset the database recovery model. 
ALTER DATABASE Db 
SET RECOVERY FULL; 
GO 

SELECT file_id, name 
FROM sys.database_files; 
GO 
DBCC SHRINKFILE (1, TRUNCATEONLY); 

如果我爲XX分鐘後,數據庫備份,然後將備份文件的大小爲1GB這樣,我可以看到未使用的空間已被成功清理。換句話說,上面的Sql代碼正常工作(XX分鐘後的數據庫是schrunk)。


我需要等到這個查詢(收縮操作)的問題完成,所以我努力做到以下幾點:

SELECT percent_complete, start_time, status, command, estimated_completion_time, cpu_time, total_elapsed_time 
FROM sys.dm_exec_requests 

我無法找到有關SHRINKFILE的任何信息命令在上述查詢的結果中。

enter image description here


難道我做錯了什麼?爲什麼我看不到DB收縮操作的進度?

而我的主要quesiton是:我怎樣才能等到SHRINKFILE完成? 例如,我可以從我的C#代碼查詢發送,並在這個查詢的結果中,我會得到SHRINKFILE操作是否被清除的信息?

+3

你知道,這既碎片你的數據庫和打破日誌鏈,對吧?這不是你應該*自動化的東西,因爲1)你永遠不應該*自動縮小數據庫,2)在你完成下一次完整備份之前,你的數據庫恢復能力處於危險之中。您應該只能手動執行此操作,並且在例外情況下親自關注它,直到完成爲止。否則,你會招致許多問題,其中一些是災難性的。 – RBarryYoung

+0

我同意;這就是爲什麼我需要阻止所有更改數據庫的同時收縮,例如添加刪除條目備份等。問題是這是我們的客戶需求,他們需要硬盤上未使用的空間我必須這樣做。 –

+0

對我來說也夠了,當這個過程結束,只是不知道一個進度條,所有我需要知道什麼時候SHRINKFILE操作是在例如SQL語句的處理結束SPID不再可用,我可以集中,從C# –

回答

16

測量DBCC SHRINKFILE進度的問題在於引擎無法知道收縮文件需要做多少工作。要了解這是知道如何DBCC SHRINKFILE工作。基本上,這個過程是:

  • 你申報你想一個文件收縮到一定程度(比如5 GB, 從10 GB下降)。
  • 引擎將開始將文件末尾的頁面移動到文件開頭附近的下一個打開位置。

Shrink File Movement

  • 發動機保持下去,直到A)它移動你的聲明點下足夠多的網頁,它可以減小文件大小或B),所有的空空間上的後端文件。

那麼爲什麼這意味着SQL Server不知道需要完成多少工作?因爲它不知道你的空白空間在文件中是如何分散的。如果事情壓縮得相當好,並且靠近文件的前端,縮小文件將會很快。否則,可能需要很長時間。好消息是,一旦頁面在文件中移動,它們就會移動。取消收縮文件不會撤消/回滾這項工作,所以如果您的縮小文件運行一段時間,然後在完成之前將其取消,那麼所有頁面移動都會保持不變。這意味着您可以重新啓動收縮文件幾乎您離開的位置(禁止在文件中創建任何新頁面)。

+0

感謝您的回答;這是真的,你說什麼,但我怎麼能檢測到收縮操作正在運行!?我可以將它彙集到它完成。 –

+1

您可以在sp_who2下的命令DbccSpaceReclaim或使用[sp_whoisactive](http://sqlblog.com/files/default.aspx)中查看它。 –

+0

我看不到DbCCSpaceReclaim但我可以看到的財產以後新的名爲AWAITINGCOMMAND此次來到新的直接收縮後我將迎來SPID,我會檢查它,如果這個收縮過程中,我將等待該SPID將結束非常感謝,我將迎來答案當我完成的時候。 –

0

我有解決以不同的方式問題,但這種解決方案並不需要任何查詢或等待線程,則很實踐。

這種做法不會重新組織表索引,但只有從硬盤中刪除的文件流和回收的自由空間OS。

重要的是要知道下面的代碼將在同一個線程上工作;所以這不會影響你關於Shrink進程的進展,而只能在應用程序線程上運行它。

var db = EFDbContext; 
    try 
    { 
     db.ExecuteSqlCommand(@"USE [master] 

            ALTER DATABASE DatabaseName 
            SET RECOVERY SIMPLE"); 

     db.ExecuteSqlCommand(@"USE [master] 

            EXEC sp_filestream_force_garbage_collection 'DatabaseName'"); 

     db.ExecuteSqlCommand(@"USE [master] 

            EXEC sp_filestream_force_garbage_collection 'DatabaseName'"); 
     } 

    } 
    catch (Exception e) 
    { 
     throw new DatabaseException(e.Message, e); 
    } 
    finally 
    { 
      db.ExecuteSqlCommand(@"USE [master] 
            ALTER DATABASE DatabaseName 
            SET RECOVERY FULL"); 
    }