如何强制执行文件流垃圾回收器以最高优先级完成其工作?

6
在阅读了这个问题之后,我明白了我需要尽可能快地执行垃圾回收。
如何告诉SQL Server filestream的垃圾回收器删除所有具有高优先级的文件?
我尝试使用CHECKPOINT语句,甚至设置了持续时间(CHECKPOINT 100),但没有任何变化。
在删除了40000个filestream记录之后,我发现垃圾回收器每秒钟可以删除4-5个文件。如何告诉它“现在全部删除”?
3个回答

18

目前无法强制回收(GC)文件流数据。它由异步后台任务处理,只有在某些时候才会被调用,并且在单次调用中可以处理的文件数量有限。其他人已经抱怨过这个问题,微软承诺将在未来的版本中解决这个问题。

尽管如此,您可以采取一些主动措施,以确保所有已删除的文件都适合进行垃圾回收。从数据库中删除文件时,文件并不会立即变为可进行垃圾回收的状态——必须满足某些附加条件。

这些条件取决于数据库的恢复模型,因此重要的是要知道您的数据库使用的恢复模型是什么。请注意,即使恢复模型(由sys.databases指定)为全量恢复模型,但如果自启用全量恢复模型(或创建数据库)以来您还没有进行过数据库/日志备份,则该数据库在很多方面的行为都类似于简单恢复模型。

在简单恢复模型下,一个文件变为可删除状态所需的条件只是当前检查点LSN(最后一个检查点的LSN)大于删除文件的LSN。因此,删除40,000行之后,您只能发出一个CHECKPOINT语句并等待。

当数据库处于“真正的全量”恢复模型时,情况变得更加复杂。如果是这种情况,则除了检查点LSN之外,备份LSN(最后一个日志备份的LSN)也必须超过删除LSN。此外,GC分为两个阶段:在第一次遍历中,它仅标记文件以进行删除,但不会物理删除它。只有在GC第二次处理该文件时,该文件才会从磁盘上被物理删除。更有趣的是,GC的第一次遍历“重置”了删除LSN,因此只有在检查点LSN和备份LSN大于第一次GC遍历的LSN时,第二次遍历才能处理该文件。

如果您想确切地了解系统中正在发生的情况,可以通过查看特殊的内部“墓碑”表来跟踪当前的GC进度。每次从数据库中删除文件流值时,都会向此表中插入一个墓碑。只有在文件从磁盘中删除后,才会删除墓碑。墓碑表的名称为sys.filestream_tombstone_,其中 是一些数字。您可以使用以下查询获取确切的名称:

select name from sys.internal_tables where name like '%tombstone%'

由于这是一张内部表格,如果想要查询它,你需要使用DAC(专用管理员连接)进行登录。


例如,假设我已经删除了一个包含单个filestream值的行。现在我可以通过以下查询(来自DAC)查看墓碑状态:

select * from sys.filestream_tombstone_2073058421

oplsn_fseqno | oplsn_bOffset | oplsn_slotid | file_id | rowset_guid | column_guid | filestream_value_name | transaction_sequence_num |status

31 | 239 | 2 | 65537 | CBA21DD0-C36F-4D19-A59B-F5312712A8F6 | 6D2AA35E-692C-4F7D-8412-94475E76AC25 | 0000001f-000000eb-0002 | 0 | 17

前三个字段表示删除操作的 LSN,但最重要的是观察 status 字段。在运行日志备份和检查点几秒钟后,再次查询墓碑表:

oplsn_fseqno | oplsn_bOffset | oplsn_slotid | file_id | rowset_guid | column_guid | filestream_value_name | transaction_sequence_num |status

31 | 265 | 2 | 65537 | CBA21DD0-C36F-4D19-A59B-F5312712A8F6 | 6D2AA35E-692C-4F7D-8412-94475E76AC25 | 0000001f-000000eb-0002 | 0 | 18

请注意,状态已更改(最后2位从1变为2),表示文件已由第一个 GC pass 处理。此外,LSN 已更新为第一个 GC pass 的 LSN,因此为了使第二个 GC pass 能够最终删除文件,我们需要将检查点 LSN 和备份 LSN 提高到新 LSN 以上。我发出另一个检查点+日志备份,等待几秒钟并重新查询 tombstones 表。现在它为空,并且该文件已从磁盘中消失。

请记住,还有其他因素(例如复制、启用版本控制的其他事务)可能会阻止特定文件被垃圾回收,但在大多数情况下,检查点和日志备份是两个主要因素。

抱歉,我可能深入了一些细节,但也许这会在某种程度上帮助理解 GC 行为。


非常详细,感谢您的解释。这将迫使我更多地了解恢复模式。 - UnDiUdin
过去7年中有没有对此进行任何更改?如果您能提供一个带有特定版本信息的更新答案,那将非常棒。 - BatteryBackupUnit

5
显然,现在有一种方法,可以通过使用
sp_filestream_force_garbage_collection

在SQL Server 2012中


1
我尝试了这个存储过程,但它与在2008R2中调用checkpoint没有太大区别,而且速度也不快... - UnDiUdin

-1

我没有可以测试的环境,但你尝试切换到简单恢复模式了吗?


你能解释得更清楚一些吗?据我所记,简单恢复模式是用于备份/还原的... 你能给我更多的细节吗?谢谢。 - UnDiUdin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接