【问题标题】:FILESTREAM files being left behind after row deleted删除行后遗留的 FILESTREAM 文件
【发布时间】:2026-01-13 04:20:05
【问题描述】:

我已经在我的 SQL 2008 服务器上成功设置了 FILESTREAM;但是我注意到,即使我删除了包含 FILESTREAM 数据的行,物理数据文件似乎也没有被删除。

物理文件是指 SQLServer 托管目录中以唯一标识符作为文件名的文件,而不是添加到 dbase 中的原始文件。

有谁知道 SQLServer 最终是否会删除该文件?如果从 dbase 中删除了很多大文件,我希望能够快速回收空间。

【问题讨论】:

    标签: sql sql-server-2008 blob filestream


    【解决方案1】:

    FILESTREAM 数据受事务控制,因此不会立即删除。

    相反,SQL Server 运行垃圾收集器,当确定旧数据最终被删除时,它会清除旧数据。

    来自documentation

    FILESTREAM 垃圾回收是由数据库检查点进程触发的后台任务。当生成足够的事务日志时,会自动运行检查点。有关详细信息,请参阅 SQL Server 2008 联机丛书 主题“CHECKPOINT 和日志的活动部分”(http://msdn.microsoft.com/en-us/library/ms189573.aspx)。鉴于FILESTREAM 文件操作最少记录在数据库的事务日志中,可能需要一段时间才能生成的事务日志记录数触发检查点进程并发生垃圾收集。如果这成为问题,您可以使用CHECKPOINTstatement 强制垃圾回收。

    【讨论】:

      【解决方案2】:

      使用

      sp_filestream_force_garbage_collection
      

      不幸的是,这只适用于 >= SQL Server 2012

      【讨论】:

      • 仅供参考 - 这仅适用于 SQL 2012
      • 好的,谢谢。我也需要那个。升级到 2012 的一个很好的理由!
      • 我在我的本地 SQL Server 2012 Express 上试过这个,但它似乎不起作用。
      • 如果你想让它立即开始工作,调用它两次,它就会开始在后台删除文件。可能需要很长时间,具体取决于文件的数量
      • @corix010 如果它不起作用,请检查数据库的恢复模式。如果已满,请将其更改为简单,然后再次运行该命令。它会工作
      【解决方案3】:

      首先,您必须为Garbage Collector 工作创建一个Checkpoint。删除行后,您可以运行此代码以消除所有不属于任何行的文件。

      USE [DataBaseName]
      GO
      
      -- Create a checkpoint on current database
      CHECKPOINT
      GO 
      
      -- Execute Garbage Collector after a checkpoint created
      EXEC sp_filestream_force_garbage_collection  'DataBaseName'
      GO
      

      【讨论】:

        【解决方案4】:

        DELETE FROM tbl_XXX DECLARE @test CHECKPOINT @test = 0

        在你的 sql server 中运行 并且您还可以观察到文件也从文件系统中删除..

        您可以设置执行删除操作后等待垃圾收集器从文件系统中清理文件的分钟数或秒数。

        谢谢

        哈拉纳特

        【讨论】:

        • 更简单:从表检查点删除
        • @DanDan 我知道这就像几年前一样,但我只想警告其他用户在使用DELETE FROM table CHECKPOINT 命令时意外删除表中所有行的危险。我试过了,它删除了我表中的所有行。幸运的是,我的表只包含示例数据。