Falha no SHRINKFILE - Por que o aumento do tamanho do arquivo resolve isso?

10

Estou executando algumas SHRINKFILEoperações para limpar um monte de pequenos arquivos desnecessários em um grupo de arquivos. Para um dos encolhimentos, o comando abaixo resulta em um erro:

DBCC SHRINKFILE (N'myfile' , EMPTYFILE)'

O ID do arquivo x do ID do banco de dados x não pode ser reduzido, pois está sendo reduzido por outro processo ou está vazio

Não está vazio nem está sendo encolhido. Ele está sendo executado em um banco de dados que não está sendo usado atualmente por ninguém, exceto eu. A redução automática não está ativada e nunca foi. No entanto, não eram psiquiatras manuais realizadas nesse banco de dados em uma base regular antes de me colocar minhas mãos nele, se o que importa em tudo.

No SQLServerCentral , um encadeamento de uma década atrás sugere adicionar alguns MB ao arquivo porque "redefine um contador interno ou um comutador que indica que ele não está no meio de uma retração agora".

Isso funcionou - incrível. Mas alguém pode explicar com mais detalhes como / por que isso funciona em relação aos internos do SQL Server?

LowlyDBA
fonte
11
Não foi possível responder a você, mas a votação é positiva, pois é um truque útil para saber se alguma vez vou me deparar com essa situação no futuro!
John Eisbrener
se você pode reproduzir novamente algum sinalizador na página do cabeçalho do arquivo que é definido durante uma redução?
Martin Smith
Sim, eu poderia dar uma chance em uma instância de teste, mas isso foi algo que definitivamente não tem o luxo de tentar reproduzi-lo lá.
LowlyDBA 18/01/19

Respostas:

5

Eu dei uma olhada na página do cabeçalho do arquivo, conforme sugerido por Martin Smith nos comentários. Acho que isso faz parte da resposta, mas é principalmente especulação baseada na observação de alterações nos valores de sinalização da página de cabeçalho do arquivo entre a realização de encolhimentos e outras operações.


Primeiro, criei um banco de dados para testar, incluindo um grupo de arquivos secundário:

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

O que eu olhei na "página 0" para o arquivo secundário, que é file_id 3:

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

Há um campo chamado m_flagBitsque tem um valor de 0x208.

Se eu esvaziar este arquivo:

DBCC SHRINKFILE (N'ShrinkFile_Test_Secondary' , EMPTYFILE);

Esse m_flagbitscampo permanece o mesmo ( 0x208). Não é tão interessante, mas agora estou na situação que você relatou: se eu tentar esvaziar o arquivo novamente, recebo este erro:

O ID do arquivo 3 do ID do banco de dados 19 não pode ser reduzido, pois está sendo reduzido por outro processo ou está vazio.

Vou tentar aumentar o arquivo (a solução que funcionou para você):

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

Agora m_flagbitsé 0x8!

Neste ponto, esvaziar o arquivo novamente com êxito retorna o valor 0x208conforme o esperado.

O que eu acho interessante é que, se eu fizer isso depois de aumentar o arquivo novamente (o valor do AKA flagbits é 0x8):

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

O arquivo está marcado como is_read_onlyna sys.databasestabela e m_flagbitsvolta para 0x208. Portanto, parece que há um sinalizador de nível de arquivo semelhante definido ao reduzir um arquivo e ao defini-lo como somente leitura.

Meu melhor palpite é que esse valor seja usado junto com algum outro sinalizador (interno) para indicar que um arquivo é elegível para ser reduzido. O aumento do arquivo parece desabilitar esse sinalizador (pelo menos o sinal visível m_flagbits).

Josh Darnell
fonte