如何告诉SQL Server filestream的垃圾回收器删除所有具有高优先级的文件?
我尝试使用CHECKPOINT语句,甚至设置了持续时间(CHECKPOINT 100),但没有任何变化。
在删除了40000个filestream记录之后,我发现垃圾回收器每秒钟可以删除4-5个文件。如何告诉它“现在全部删除”?
目前无法强制回收(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 行为。
sp_filestream_force_garbage_collection
在SQL Server 2012中
我没有可以测试的环境,但你尝试切换到简单恢复模式了吗?