Отказ SHRINKFILE - Почему увеличение размера файла разрешает это?

10

Я выполняю некоторые SHRINKFILEоперации, чтобы очистить кучу мелких ненужных файлов в файловой группе. Для одного из сокращений приведенная ниже команда приводит к ошибке:

DBCC SHRINKFILE (N'myfile' , EMPTYFILE)'

Идентификатор файла x базы данных с идентификатором x нельзя сжать, поскольку он либо сокращен другим процессом, либо пуст

Это не пусто и не сокращено. Он запускается в базе данных, которая в настоящее время не используется никем, кроме меня. Автоусадка не включена и никогда не была. Тем не менее, были ручные психиатры , выполненные в этой базе данных на регулярной основе до меня получать мои руки на нем, если это имеет значение вообще.

В SQLServerCentral поток, созданный десять лет назад, предлагает добавить в файл несколько МБ, так как он «сбрасывает внутренний счетчик или переключатель, который сообщает, что сейчас не происходит сокращения».

Это сработало - потрясающе. Но кто-нибудь может объяснить более подробно, как / почему это работает в отношении внутренних компонентов SQL Server?

LowlyDBA
источник
1
Не могу сказать вам ответ, но голосую за это, потому что это удобная уловка, чтобы узнать, столкнусь ли я когда-нибудь с этой ситуацией в будущем!
Джон Эйсбренер
если вы можете повторить, может быть, какой-нибудь флаг на странице заголовка файла, который устанавливается во время сжатия?
Мартин Смит
Да, я мог бы сделать снимок на тестовом экземпляре, но это было продвижение, так что определенно нет такой роскоши, как попытка воспроизвести его там.
LowlyDBA

Ответы:

5

Я искал в заголовке файла, как это было предложено Мартином Смитом в комментариях. Я думаю, что это часть ответа, но в основном это спекуляция, основанная на наблюдении за изменениями значений флага страницы заголовка файла между выполнением сжатия и другими операциями.


Сначала я создал базу данных для тестирования, включая вторичную файловую группу:

CREATE DATABASE [Shrinkfile_Test]
ON PRIMARY
(
    NAME = N'Shrinkfile_Test',
    FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL13.SQL2016\MSSQL\DATA\Shrinkfile_Test.mdf',
    SIZE = 8192KB,
    FILEGROWTH = 65536KB
),
FILEGROUP [SECONDARY]
(
    NAME = N'ShrinkFile_Test_Secondary',
    FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL13.SQL2016\MSSQL\DATA\ShrinkFile_Test_Secondary.ndf',
    SIZE = 1024KB,
    FILEGROWTH = 65536KB
)
LOG ON
(
    NAME = N'Shrinkfile_Test_log',
    FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL13.SQL2016\MSSQL\DATA\Shrinkfile_Test_log.ldf',
    SIZE = 73728KB,
    FILEGROWTH = 65536KB 
)
GO

USE Shrinkfile_Test;
GO

Я посмотрел на «страницу 0» для вторичного файла, который является file_id 3:

DBCC TRACEON (3604);
GO
DBCC PAGE (N'Shrinkfile_Test', 3, 0, 3);

Есть поле с именем, m_flagBitsкоторое имеет значение 0x208.

Если я опустошу этот файл:

DBCC SHRINKFILE (N'ShrinkFile_Test_Secondary' , EMPTYFILE);

Это m_flagbitsполе остается неизменным ( 0x208). Не очень интересно, но теперь я нахожусь в ситуации, о которой вы сообщили: если я попытаюсь очистить файл снова, я получу эту ошибку:

Идентификатор файла 3 базы данных с идентификатором 19 нельзя сжать, поскольку он либо сокращен другим процессом, либо пуст.

Я попробую вырастить файл (решение, которое сработало для вас):

ALTER DATABASE ShrinkFile_Test
MODIFY FILE
(
    NAME = ShrinkFile_Test_Secondary,
    SIZE = 1025KB
);
GO

Сейчас m_flagbitsесть 0x8!

На этом этапе повторная очистка файла возвращает значение, 0x208как вы могли ожидать.

Что мне кажется интересным, так это то, что если я сделаю это после того, как вырасту файл обратно (значение флажка AKA равно 0x8):

USE [master]
GO
ALTER DATABASE [Shrinkfile_Test] MODIFY FILEGROUP [SECONDARY] READONLY
GO

Файл помечен как is_read_onlyв sys.databasesтаблице и m_flagbitsустановлен обратно 0x208. Таким образом, кажется, есть некоторый подобный флаг уровня файла, установленный при сжатии файла и при установке его только для чтения.

Мое лучшее предположение состоит в том, что это значение используется вместе с некоторым другим (внутренним) флагом, чтобы указать, что файл может быть сжат. Увеличение файла, по-видимому, снимает этот флаг (по крайней мере, тот, который виден в m_flagbits).

Джош Дарнелл
источник