Error de SHRINKFILE: ¿por qué el aumento del tamaño del archivo lo resuelve?

10

Estoy ejecutando algunas SHRINKFILEoperaciones para limpiar un montón de archivos pequeños e innecesarios en un grupo de archivos. Para uno de los encogimientos, el siguiente comando genera un error:

DBCC SHRINKFILE (N'myfile' , EMPTYFILE)'

La ID de archivo x de la ID de base de datos x no se puede reducir ya que está siendo reducida por otro proceso o está vacía

No está vacío ni se encoge. Se está ejecutando en una base de datos que actualmente no está en uso por nadie excepto yo. La reducción automática no está habilitada y nunca lo estuvo. Sin embargo, no se encoge manuales realizadas en esta base de datos de forma regular antes de mí conseguir mis manos en él, si lo que importa en absoluto.

En SQLServerCentral , un subproceso de hace una década sugiere agregar algunos MB al archivo porque eso "restablece un contador interno o conmutador que le dice que ahora no está en medio de una reducción".

Esto funcionó, increíble. Pero, ¿alguien puede explicar con mayor detalle cómo / por qué esto funciona con respecto a los componentes internos de SQL Server?

LowlyDBA
fuente
1
No podría decirle la respuesta, pero votar es un truco útil para saber si alguna vez me encuentro con esta situación en el futuro.
John Eisbrener
si puede reprochar tal vez algún indicador en la página de encabezado del archivo que se configura durante una reducción
Martin Smith
Sí, podría darle una oportunidad en una instancia de prueba, pero esto fue muy bueno, así que definitivamente no tengo el lujo de intentar reproducirlo allí.
LowlyDBA

Respuestas:

5

Busqué en la página del encabezado del archivo, como lo sugirió Martin Smith en los comentarios. Creo que esto es parte de la respuesta, pero es principalmente una especulación basada en la observación de cambios en los valores de marca de la página del encabezado del archivo entre la reducción de tamaño y otras operaciones.


Primero creé una base de datos para probar, incluido un grupo de archivos secundario:

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

Miré la "página 0" para el archivo secundario, que es file_id 3:

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

Hay un campo llamado m_flagBitsque tiene un valor de 0x208.

Si vacio este archivo:

DBCC SHRINKFILE (N'ShrinkFile_Test_Secondary' , EMPTYFILE);

Ese m_flagbitscampo permanece igual ( 0x208). No es tan interesante, pero ahora estoy en la situación que informó: si trato de vaciar el archivo nuevamente, aparece este error:

El ID de archivo 3 del ID de base de datos 19 no se puede reducir, ya que otro proceso lo está reduciendo o está vacío.

Intentaré hacer crecer el archivo (la solución que funcionó para usted):

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

Ahora m_flagbitses 0x8!

En este punto, vaciar el archivo nuevamente es exitoso y devuelve el valor a 0x208lo esperado.

Lo que me parece interesante es que si hago esto después de que el archivo vuelva a crecer (el valor de AKA flagbits es 0x8):

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

El archivo se marca como is_read_onlyen la sys.databasestabla y m_flagbitsse vuelve a establecer en 0x208. Por lo tanto, parece que hay un indicador de nivel de archivo similar al reducir un archivo y al configurarlo como de solo lectura.

Mi mejor suposición es que este valor se usa junto con alguna otra bandera (interna) para indicar que un archivo es elegible para ser reducido. Al hacer crecer el archivo, parece desestabilizar esa bandera (al menos la que está visible en m_flagbits).

Josh Darnell
fuente