我正在运行一些SHRINKFILE
操作来清理文件组中的一堆微小的、不必要的文件。对于其中一个收缩,下面的命令会导致错误:
DBCC SHRINKFILE (N'myfile' , EMPTYFILE)'
数据库 ID x 的文件 ID x 无法收缩,因为它正在被另一个进程收缩或为空
它不是空的,也不是收缩的。它正在一个数据库上运行,目前除了我自己以外没有人在使用它。自动收缩未启用且从未启用。但是,如果这很重要的话,在我接触这个数据库之前,会定期对该数据库进行手动收缩。
在SQLServerCentral上,十年前的一个线程建议向文件添加几 MB,因为这“重置了一个内部计数器或开关,告诉它现在不在收缩中。”
这有效 - 太棒了。但是谁能更详细地解释这在 SQL Server 内部是如何/为什么起作用的?
正如 Martin Smith 在评论中所建议的那样,我在文件标题页中四处寻找。我认为这是答案的一部分,但它主要是基于观察执行收缩和其他操作之间文件头页面标志值的变化的猜测。
首先我创建了一个数据库来测试,包括一个辅助文件组:
我查看了辅助文件的“第 0 页”,即 file_id 3:
有一个名为的字段
m_flagBits
,其值为0x208
。如果我清空这个文件:
该
m_flagbits
字段保持不变 (0x208
)。没那么有趣,但现在我遇到了你报告的情况:如果我再次尝试清空文件,我会收到此错误:我会尝试增加文件(适合您的解决方案):
现在
m_flagbits
是0x8
!此时,再次清空文件就成功了,返回值
0x208
如你所料。我觉得有趣的是,如果我在恢复文件后执行此操作(又名标志位值是
0x8
):该文件被标记为
is_read_only
在sys.databases
表中,并m_flagbits
设置回0x208
. 因此,在缩小文件和将其设置为只读时,似乎设置了一些类似的文件级标志。我最好的猜测是此值与其他一些(内部)标志一起使用,以指示文件符合收缩条件。增大文件似乎取消了该标志的设置(至少是 中可见的标志
m_flagbits
)。