SQL Server. FILESTREAM. Сборщик "муссора". Часть 4.

В данной статье мы расскажем о системе сбора мусора (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

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

4_3.jpg

Обратите внимание на то, что документ в таблице один (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) 

3 авг. 2017 г.