Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# DBCC收缩文件的进度_C#_Sql Server_Sql Server 2012 - Fatal编程技术网

C# DBCC收缩文件的进度

C# DBCC收缩文件的进度,c#,sql-server,sql-server-2012,C#,Sql Server,Sql Server 2012,我有一个数据库21GB;其中20 Gb是文件(FileStream)并且我已经从表中删除了所有文件,但是当我进行备份时,备份文件仍然是21 Gb 为了解决这个问题,我成了“释放未使用的空间”的创意者 因此,我试图缩小我的数据库,如下所示: USE Db; GO -- Truncate the log by changing the database recovery model to SIMPLE. ALTER DATABASE Db SET RECOVERY SIMPLE; GO -- Shr

我有一个数据库21GB;其中20 Gb是文件(FileStream)并且我已经从表中删除了所有文件,但是当我进行备份时,备份文件仍然是21 Gb

为了解决这个问题,我成了“释放未使用的空间”的创意者

因此,我试图缩小我的数据库,如下所示:

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);
SELECT percent_complete, start_time, status, command, estimated_completion_time, cpu_time, total_elapsed_time
FROM sys.dm_exec_requests
如果我在XX分钟后对数据库进行备份,那么备份文件大小为1GB。这样,我可以看到未使用的空间已成功清理。换句话说,上面的Sql代码工作正常(XX分钟后的数据库是schrunk)


问题我需要等待此查询(收缩操作)完成,因此我尝试执行以下操作:

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);
SELECT percent_complete, start_time, status, command, estimated_completion_time, cpu_time, total_elapsed_time
FROM sys.dm_exec_requests
在上述查询的结果中,我找不到有关SHRINKFILE命令的任何信息


我做错什么了吗?为什么我看不到DB收缩操作的进度?

我的主要问题是:如何才能等到收缩文件完成?
例如,我可以从我的C代码查询中发送,并且在该查询的结果中,我将获得收缩文件操作是否已找到的信息吗?

测量DBCC SHRINKFILE进度的问题是,引擎无法一致地知道收缩文件需要做多少工作。要理解这一点,就要知道
DBCC SHRINKFILE
是如何工作的。基本上,这个过程是:

  • 您声明要将文件压缩到某一点(例如5 GB, 从10GB下降)
  • 引擎将开始将页面从文件末尾移动到文件开头附近的下一个打开位置

  • 引擎一直运行,直到A)它在声明的点下移动了足够多的页面以减小文件大小,或B)所有的空白都在文件的后端

那么,为什么这意味着SQL Server不知道需要做多少工作呢?因为它不知道文件中的空白空间有多零碎。如果文件压缩得相当好,并且靠近文件的前面,则收缩文件将快速移动。如果没有,可能需要很长时间。好消息是,一旦页面在文件中移动,它们就会被移动。取消收缩文件不会撤消/回滚此工作,因此,如果收缩文件运行一段时间,然后在完成之前将其杀死,则所有页面移动都将保持不变。这意味着您可以在几乎停止的位置重新启动收缩文件(禁止在文件中创建任何新页面)。

我已经用不同的方法解决了这个问题,但是这个解决方案不需要任何轮询或等待线程,而且非常实用

这种方法不会重新组织表索引,只会从硬盘中删除流文件,并将可用空间回收给操作系统

重要的是要知道下面的代码将在同一线程上工作;因此,这不会告诉您收缩过程的进度,而只会在应用程序线程上运行它

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

谢谢你的回答;你说的没错,但我怎么能检测到收缩操作正在运行!?我可以集中它直到它完成。你可以在sp_who2下看到它,命令是DbccSpaceReclaim或正在使用。我看不到DbccSpaceReclaim,但我可以看到一个新的叫做waitingcommand的命令,它在收缩后直接出现。我会标记SPID,我会检查它,如果这是收缩过程,我会一直等到这个SPID完成,谢谢,我会的完成时标记答案。我将在sp#U who2中的所有SPID期间循环,并使用eventInfo ShrinkFile中的dbcc inputbuffer,我可以看到进程正在进行、正在休眠或正在运行,我将从C#中轮询它,或者确保作业是否完成,或者在存储过程中完成时,我将使用SqlDependency触发事件。I将发布我的Stroed过程(检测ShrinkFile正在运行),您可以在回答中进行更新。您确实意识到这会破坏您的数据库并破坏日志链,对吗?这不是您应该自动执行的操作,因为1)您永远不应该自动收缩数据库,2)在完成下一次完全备份之前,您的数据库恢复能力处于危险之中。你只应该在例外情况下手动执行此操作,并亲自监视,直到完成为止。否则你会带来很多问题,其中一些是灾难性的;这就是为什么我需要在收缩时阻止所有更改数据库的操作,例如添加删除条目备份,等等。问题是我们的客户要求,他们需要硬盘上未使用的空间,我必须这样做。对我来说,只要知道这个过程何时完成就足够了,而不是进度条。我只需要知道ShrinkFile操作何时在SQL语句中完成,例如,过程SPID不再可用,我可以从C#我对回收或减少数据库大小的任何新想法都持开放态度。如果你可以在不备份的情况下将数据库的恢复模式从完全模式更改为简单模式,那么在这种情况下为什么需要完全模式?在简单恢复模式下,数据库使用的空间可以减少…此脚本的作用是什么?