Блог инженеров технической поддержки SQL Server. Microsoft. Россия

Блог инженеров технической поддержки SQL Server. Microsoft. Россия

SQL Server FILESTREAM сборщик мусора (garbage collection)

В данной статье мы расскажем о системе сбора мусора (FILESTREAM garbage collection), отвечающей за удаление ненужных (удаленных) файлов.

Просмотрим содержимое документа, загруженного в FILESTREAM.

use FileStreamTest;
GO
SELECT cast (Document as char(100) ) as [Document text]
FROM dbo.FS_Records
WHERE DocId = 2;

Document text
Yes, it”s work fine                                                                               

Выполним обновление поля таблицы. Мы будем выполнять полное обновление поля, поскольку выполнение частичного обновления FILESTREAM-данных при помощи Transact-SQL невозможно, это возможно только сделать с помощью Win32 API. 

UPDATE FS_Records
SET Document = CAST(‘It is updated column’ as varbinary(max))
WHERE DocId = 2;

Просмотрим содержимое обновленного документа.

use FileStreamTest;
GO
SELECT cast (Document as char(100) ) as [Document text]
FROM dbo.FS_Records
WHERE DocId = 2;

Document text
It’s updated column                                                              

Выполним запрос к таблице.

DocGUID DocId Document
A2EABE03-9647-460B-A52F-47D214191B32 1 NULL
B16BC7B7-D337-4D52-A2CC-C4695C629362 2 0x4974206973207570646174656420636F6C756D6E

Посмотрим файлы в файловой системе.


Обратите внимание на то, что документ в таблице один (DocId=2, так как документ для DocId=1 равен NULL, т.е. его попросту нет), а файла два. Почему?

Откроем эти файлы с помощью Notepad.exe (Хотя в реальной жизни делать этого настоятельно не рекомендуется).

Файл с именем “0000002a-00000150-0006” содержит “Yes, it”s work fine”.

Файл с именем “0000002a-00000180-0005” содержит “It is updated column”.

Таким образом SQL Server оставил старый файл для дальнейшего удаления сборщиком мусора.

Откуда сервер берет информацию о файлах, которые должны быть удалены?

Выполним второе подключение через DAC и выполним запрос.

use FileStreamTest;
GO
select *
from sys.internal_tables
where name like ‘filestream_tombstone%’;

Мы увидим строку с именем в поле “name” что-то похожее на “filestream_tombstone_2073058421”. Это имя внутренней таблицы содержащей данные необходимые сборщику мусора для удаления ненужных файлов.

Выполним запрос к этой таблице.

select rowset_guid, column_guid, filestream_value_name
from sys.filestream_tombstone_2073058421;

rowset_guid column_guid filestream_value_name
04E6A56A-9457-4DD3-8B1F-AC0F49A49B0A 38E656D7-2CFB-43C8-AE98-F489B57F6D7D 0000002a-00000150-0006

Как видно из результатов запроса, в этой таблице есть вся необходимая информация для работы системы сбора мусора (Garbage collection). Есть имена папок и имя файла подлежащего удалению.

Исходя из алгоритма, описанного выше, при обновлении FILESTREAM через Transact-SQL файловая система может быть перегружена файлами потребность в которых отсутствует. 

Для решения этой проблемы возможно использование Win32 API, позволяющего производить частичное обновление файлов, что не приведет к появлению нового файла.

Если вам необходимо принудительно инициировать процесс сбора мусора, то можно вызвать встроенную хранимую процедуру [sys].[sp_filestream_force_garbage_collection].

Однако очистка произойдет только при выполнении следующих условий:

1. Если база находится в режиме FULL RECOVERY, то очистка производится только для файлов, которые были удалены в рамках закрытых и подвергшихся резервному копированию VLF (Virtual Log File).

2. Если база находится в SIMPLE RECOVERY, то очистка производится только для файлов, которые были удалены в рамках закрытых VLF.

Т.е. если файл был удален, а VLF, где размещена транзакция удаления файла не закрыт, то Garbage collection не будет удалять такой файл ни при каком условии.

В следующем нашем блоге мы рассмотрим как получит доступ к FILESTREAM-файлам через Win32 API используя программный код написанный на C#.

 

Александр Каленик, Senior Premier Field Engineer (PFE), MSFT (Russia)