正如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标志位值为0x8
):
USE [master]
GO
ALTER DATABASE [Shrinkfile_Test] MODIFY FILEGROUP [SECONDARY] READONLY
GO
该文件is_read_only
在sys.databases
表中标记为,并m_flagbits
设置回0x208
。 因此,在缩小文件并将其设置为只读时,似乎设置了一些类似的文件级标志。
我最好的猜测是,此值与其他(内部)标志一起使用以指示文件可以收缩。增大文件似乎会取消设置该标记(至少在中可见m_flagbits
)。