SHRINKFILE 失败 - 为什么增加文件大小可以解决它?

Low*_*n M 10 sql-server shrink dbcc sql-server-2016

我正在运行一些SHRINKFILE操作来清理文件组中的一堆微小的、不必要的文件。对于其中一种收缩,以下命令会导致错误:

DBCC SHRINKFILE (N'myfile' , EMPTYFILE)'
Run Code Online (Sandbox Code Playgroud)

数据库 ID x 的文件 ID x 无法收缩,因为它正在被另一个进程收缩或为空

它不是空的,也不是被缩小的。它正在一个数据库上运行,除了我自己,其他人目前都没有使用它。自动收缩未启用且从未启用。但是,在我开始使用它之前,会定期对这个数据库进行手动收缩,如果这很重要的话。

SQLServerCentral 上,十年前的一个线程建议向文件添加几 MB,因为这“会重置一个内部计数器或开关,告诉它现在不在缩小中间。”

这有效 - 太棒了。但是任何人都可以更详细地解释如何/为什么在 SQL Server 内部工作?

Jos*_*ell 5

正如 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
Run Code Online (Sandbox Code Playgroud)

我查看了辅助文件的“第 0 页”,即 file_id 3:

DBCC TRACEON (3604);
GO
DBCC PAGE (N'Shrinkfile_Test', 3, 0, 3);
Run Code Online (Sandbox Code Playgroud)

有一个名为 的字段m_flagBits,其值为0x208

如果我清空这个文件:

DBCC SHRINKFILE (N'ShrinkFile_Test_Secondary' , EMPTYFILE);
Run Code Online (Sandbox Code Playgroud)

m_flagbits字段保持不变 ( 0x208)。没那么有趣,但现在我处于您报告的情况:如果我再次尝试清空文件,则会收到此错误:

数据库 ID 19 的文件 ID 3 不能收缩,因为它要么被另一个进程收缩,要么为空。

我会尝试增加文件(适合您的解决方案):

ALTER DATABASE ShrinkFile_Test
MODIFY FILE
(
    NAME = ShrinkFile_Test_Secondary,
    SIZE = 1025KB
);
GO
Run Code Online (Sandbox Code Playgroud)

现在m_flagbits0x8

此时,再次清空文件是成功的,0x208如您所料,返回值。

我觉得有趣的是,如果我在将文件放回后执行此操作(AKA 标志位值为0x8):

USE [master]
GO
ALTER DATABASE [Shrinkfile_Test] MODIFY FILEGROUP [SECONDARY] READONLY
GO
Run Code Online (Sandbox Code Playgroud)

该文件被标记为is_read_onlysys.databases表中,m_flagbits设置回0x208因此,在缩小文件并将其设置为只读时,似乎设置了一些类似的文件级标志。

我最好的猜测是,该值与其他一些(内部)标志一起使用,以指示文件可以收缩。增长文件似乎取消设置该标志(至少在 中可见m_flagbits)。