SHRINKFILE 失敗 - 為什麼增加文件大小可以解決它?
我正在執行一些
SHRINKFILE
操作來清理文件組中的一堆微小的、不必要的文件。對於其中一種收縮,以下命令會導致錯誤:DBCC SHRINKFILE (N'myfile' , EMPTYFILE)'
數據庫 ID x 的文件 ID x 不能被收縮,因為它要麼被另一個程序收縮,要麼為空
它不是空的,也不是縮小的。它正在一個數據庫上執行,除了我自己之外,其他人目前都沒有使用它。自動收縮未啟用,也從未啟用。但是,在我開始使用它之前,會定期對這個數據庫進行手動縮減,如果這很重要的話。
在SQLServerCentral上,十年前的一個執行緒建議向文件添加幾 MB,因為這“重置了一個內部計數器或開關,告訴它它現在沒有處於收縮的中間”。
這工作 - 太棒了。但是任何人都可以更詳細地解釋這在 SQL Server 內部是如何/為什麼起作用的嗎?
正如 Martin Smith 在評論中所建議的那樣,我在文件標題頁面中四處尋找。我認為這是答案的一部分,但它主要是基於觀察執行收縮和其他操作之間文件頭頁標誌值的變化的推測。
首先,我創建了一個用於測試的數據庫,包括一個輔助文件組:
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
)。沒那麼有趣,但是現在我遇到了您報告的情況:如果我再次嘗試清空文件,則會收到此錯誤:數據庫 ID 19 的文件 ID 3 不能被收縮,因為它要麼被另一個程序收縮,要麼是空的。
我會嘗試增加文件(對你有用的解決方案):
ALTER DATABASE ShrinkFile_Test MODIFY FILE ( NAME = ShrinkFile_Test_Secondary, SIZE = 1025KB ); GO
現在
m_flagbits
是0x8
!此時,再次清空文件成功返回值,
0x208
如您所料。我發現有趣的事情是,如果我在文件增長後執行此操作(AKA flagbits 值為
0x8
):USE [master] GO ALTER DATABASE [Shrinkfile_Test] MODIFY FILEGROUP [SECONDARY] READONLY GO
is_read_only
該文件在sys.databases
表中標記為,並m_flagbits
設置回0x208
. 因此,在縮小文件並將其設置為只讀時,似乎設置了一些類似的文件級標誌。我最好的猜測是該值與其他一些(內部)標誌一起使用,以指示文件有資格被縮小。增大文件似乎會取消設置該標誌(至少是 中可見的標誌
m_flagbits
)。