SHRINKFILE-Fehler - Warum wird er durch Erhöhen der Dateigröße behoben?

10

Ich SHRINKFILEführe einige Vorgänge aus, um ein paar winzige, unnötige Dateien in einer Dateigruppe zu bereinigen. Bei einem der Shrinks führt der folgende Befehl zu einem Fehler:

DBCC SHRINKFILE (N'myfile' , EMPTYFILE)'

Die Datei-ID x der Datenbank-ID x kann nicht verkleinert werden, da sie entweder von einem anderen Prozess verkleinert wird oder leer ist

Es ist weder leer noch geschrumpft. Es wird in einer Datenbank ausgeführt, die derzeit nur von mir selbst verwendet wird. Das automatische Verkleinern ist nicht aktiviert und war es nie. Es wurden jedoch regelmäßig manuelle Verkleinerungen an dieser Datenbank durchgeführt, bevor ich sie in die Hände bekam, wenn das überhaupt wichtig ist.

In SQLServerCentral schlägt ein Thread aus einem Jahrzehnt vor, der Datei einige MB hinzuzufügen, da dies "einen internen Zähler oder Schalter zurücksetzt, der angibt , dass er sich gerade nicht in der Mitte eines Schrumpfens befindet".

Das hat funktioniert - super. Aber kann jemand genauer erklären, wie / warum dies in Bezug auf SQL Server-Interna funktioniert?

LowlyDBA
quelle
1
Konnte Ihnen die Antwort nicht sagen, aber Upvoting, da dies ein praktischer Trick ist, um zu wissen, ob ich in Zukunft jemals auf diese Situation stoße!
John Eisbrener
Wenn Sie vielleicht ein Flag auf der Datei-Header-Seite erneut drucken können, das während eines Verkleinerns gesetzt wird?
Martin Smith
Ja, ich könnte das auf einer Testinstanz ausprobieren, aber das war ein Produkt, also habe ich definitiv nicht den Luxus, es dort zu reproduzieren.
LowlyDBA

Antworten:

5

Ich stöberte in der Datei-Header-Seite herum, wie von Martin Smith in den Kommentaren vorgeschlagen. Ich denke, dies ist Teil der Antwort, aber es handelt sich hauptsächlich um Spekulationen, die auf der Beobachtung von Änderungen an den Flag-Werten der Dateikopfzeilen-Seite zwischen dem Ausführen von Verkleinerungen und anderen Vorgängen beruhen.


Zuerst habe ich eine Datenbank zum Testen erstellt, einschließlich einer sekundären Dateigruppe:

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

Ich habe auf "Seite 0" nach der sekundären Datei gesucht, die file_id 3 ist:

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

Es gibt ein Feld mit m_flagBitsdem Wert 0x208.

Wenn ich diese Datei leere:

DBCC SHRINKFILE (N'ShrinkFile_Test_Secondary' , EMPTYFILE);

Dieses m_flagbitsFeld bleibt gleich ( 0x208). Nicht so interessant, aber jetzt bin ich in der Situation, die Sie gemeldet haben: Wenn ich versuche, die Datei erneut zu leeren, wird folgende Fehlermeldung angezeigt:

Die Datei-ID 3 der Datenbank-ID 19 kann nicht verkleinert werden, da sie entweder von einem anderen Prozess verkleinert wird oder leer ist.

Ich werde versuchen, die Datei zu erweitern (die Lösung, die für Sie funktioniert hat):

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

Jetzt m_flagbitsist 0x8!

Zu diesem Zeitpunkt ist das erneute Leeren der Datei erfolgreich, und der Wert wird 0x208wie erwartet zurückgegeben.

Das, was ich interessant finde, ist, dass wenn ich dies nach dem Zurückwachsen der Datei mache (AKA Flagbits-Wert ist 0x8):

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

Die Datei ist wie is_read_onlyin der sys.databasesTabelle markiert und m_flagbitswird auf zurückgesetzt 0x208. Es scheint also, dass ein ähnliches Flag auf Dateiebene gesetzt ist, wenn eine Datei verkleinert und auf schreibgeschützt gesetzt wird.

Ich vermute, dass dieser Wert zusammen mit einem anderen (internen) Flag verwendet wird, um anzuzeigen, dass eine Datei verkleinert werden kann. Wenn Sie die Datei vergrößern, wird dieses Flag anscheinend deaktiviert (zumindest das in m_flagbits).

Josh Darnell
quelle