Błąd SHRINKFILE - Dlaczego zwiększenie rozmiaru pliku to rozwiązuje?

10

Przeprowadzam kilka SHRINKFILEoperacji, aby oczyścić kilka małych, niepotrzebnych plików w grupie plików. W przypadku jednego z obkurczeń poniższe polecenie powoduje błąd:

DBCC SHRINKFILE (N'myfile' , EMPTYFILE)'

Identyfikator pliku x identyfikatora bazy danych x nie może zostać zmniejszony, ponieważ jest on zmniejszany przez inny proces lub jest pusty

Nie jest pusty ani się nie kurczy. Jest uruchamiany w bazie danych, która nie jest obecnie używana przez nikogo oprócz mnie. Automatyczne zmniejszanie nie jest włączone i nigdy nie było. Jednak w tej bazie danych regularnie dokonywano ręcznych obkurczeń, zanim dotarłem do niej, jeśli to w ogóle ma znaczenie.

W SQLServerCentral wątek sprzed dekady sugeruje dodanie do pliku kilku MB, ponieważ to „resetuje wewnętrzny licznik lub przełącznik, który mówi, że nie jest teraz w trakcie zmniejszania”.

To zadziałało - niesamowite. Ale czy ktoś może bardziej szczegółowo wyjaśnić, w jaki sposób / dlaczego to działa w odniesieniu do wewnętrznych elementów SQL Server?

LowlyDBA
źródło
1
Nie mogłem odpowiedzieć na pytanie, ale głosowanie, ponieważ jest to przydatna sztuczka, aby wiedzieć, czy kiedykolwiek napotkam taką sytuację w przyszłości!
John Eisbrener,
jeśli możesz repro, może jakaś flaga na stronie nagłówka pliku, która jest ustawiana podczas zmniejszania?
Martin Smith,
Tak, mógłbym dać temu szansę na testową instancję, ale to było cudowne, więc zdecydowanie nie mam luksusu, próbując go tam odtworzyć.
LowlyDBA

Odpowiedzi:

5

Przeszukiwałem stronę nagłówka pliku, jak sugerował Martin Smith w komentarzach. Myślę, że jest to część odpowiedzi, ale jest to głównie spekulacja oparta na obserwowaniu zmian wartości flag strony nagłówka pliku między wykonywaniem skurczów a innymi operacjami.


Najpierw utworzyłem bazę danych do testowania, w tym dodatkową grupę plików:

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

Spojrzałem na „stronę 0” dla drugiego pliku, którym jest file_id 3:

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

Istnieje pole o nazwie, m_flagBitsktóre ma wartość 0x208.

Jeśli opróżnię ten plik:

DBCC SHRINKFILE (N'ShrinkFile_Test_Secondary' , EMPTYFILE);

To m_flagbitspole pozostaje takie samo ( 0x208). Nie tak interesujące, ale teraz jestem w sytuacji, którą zgłosiłeś: jeśli spróbuję ponownie opróżnić plik, pojawia się ten błąd:

Identyfikator pliku 3 identyfikatora bazy danych 19 nie może zostać zmniejszony, ponieważ jest albo zmniejszany przez inny proces, albo jest pusty.

Spróbuję rozbudować plik (rozwiązanie, które Ci się udało):

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

Teraz m_flagbitsjest 0x8!

W tym momencie ponowne opróżnienie pliku zakończy się powodzeniem i zwraca wartość, 0x208zgodnie z oczekiwaniami.

Interesujące jest dla mnie to, że jeśli zrobię to po wyodrębnieniu pliku (wartość flagówek AKA to 0x8):

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

Plik jest oznaczony jak is_read_onlyw sys.databasestabeli i m_flagbitsustawiony jest z powrotem na 0x208. Wygląda więc na to, że podczas zmniejszania pliku i ustawiania go jako tylko do odczytu ustawiono podobną flagę na poziomie pliku.

Domyślam się, że ta wartość jest używana wraz z jakąś inną (wewnętrzną) flagą wskazującą, że plik kwalifikuje się do zmniejszenia. Wydaje się, że powiększenie pliku powoduje wyłączenie tej flagi (przynajmniej tej widocznej w m_flagbits).

Josh Darnell
źródło