# rm-rf.es

WSUS: llenado de base de datos SUSDB SQL Server Express

Como la mayoría sabéis, SQL Server Express tiene una limitación máxima de 10GB para el tamaño de las bases ed datos. Windows Server Update Services (también llamado WSUS), es un sistema que permite centralizar actualizaciones de seguridad para los sistemas operativos Microsoft. Muchas veces la instalación se realiza con SQL Server Express. Tras años de acumulación de parches, si no se realiza un mantenimiento de la base de datos (SUSDB), terminará llenándose.

Algunos ejemplos de error:

No se pudo asignar espacio para el objeto ‘dbo.tbXml’ .’PK__tbXml__D14A66A9DC08519F’ de la base de datos ‘SUSDB’ porque el grupo de archivos ‘PRIMARY’ está lleno. Elimine archivos innecesarios, quite objetos del grupo de archivos, agregue archivos adicionales al grupo de archivos o establezca la opción de crecimiento automático para los archivos existentes en el grupo de archivos con el fin de crear espacio en el disco.

Error en CREATE DATABASE o ALTER DATABASE. El tamaño de base de datos acumulado superaría el límite de la licencia de 10240 MB por base de datos.

Inicialmente, la solución pasa por ejecutar el asistente de limpieza de WSUS directamente a través de la aplicación. El asistente ofrece las siguientes opciones:

El problema es que si tenemos una gran cantidad de actualizaciones acumuladas en WSUS, es muy probable que este asistente no funcione como debe y genere TIMEOUT. La solución pasa por ejecutar el procedimiento directamente desde SQL Server Management Studio contra la base de datos.

Lo primero que podemos lanzar es el Procedimiento almacenado de Microsoft que muestra los objetos que expirados/obsoletos que se pueden borrar:

USE SUSDB
EXEC spGetObsoleteUpdatesToCleanup

Después, el siguiente procedimiento en modo batch permite lanzar la limpieza en bloques para evitar saturar la base de datos. Se puede cambiar por el número de objetos a borrar en cada iteración, IF @curitem 10:

Recordad parar el servicio de WSUS antes de ejecutar la limpieza directamente en BD.

USE SUSDB
DECLARE @var1 INT, @curitem INT, @totaltodelete INT
DECLARE @msg nvarchar(200)
CREATE TABLE #results (Col1 INT) INSERT INTO #results(Col1)
EXEC spGetObsoleteUpdatesToCleanup
SET @totaltodelete = (SELECT COUNT(*) FROM #results)
SELECT @curitem=1
DECLARE WC Cursor FOR SELECT Col1 FROM #results
OPEN WC
FETCH NEXT FROM WC INTO @var1 WHILE (@@FETCH_STATUS > -1)
BEGIN SET @msg = cast(@curitem as varchar(5)) + '/' + cast(@totaltodelete as varchar(5)) + ': Deleting ' + CONVERT(varchar(10), @var1) + ' ' + cast(getdate() as varchar(30))
RAISERROR(@msg,0,1) WITH NOWAIT
EXEC spDeleteUpdate @localUpdateID=@var1
SET @curitem = @curitem +1
IF @curitem < 10
FETCH NEXT FROM WC INTO @var1
END
CLOSE WC
DEALLOCATE WC
DROP TABLE #results

Al no tener índices específicos, esta tarea es muy costosa en tiempo, un minuto por cada registro a eliminar. Existe la opcion de crear los siguientes indices para acelerar la tarea.

USE [SUSDB]
GO
CREATE NONCLUSTERED INDEX [IX_tbRevisionSupersedesUpdate] ON [dbo].[tbRevisionSupersedesUpdate]([SupersededUpdateID])
GO
CREATE NONCLUSTERED INDEX [IX_tbLocalizedPropertyForRevision] ON [dbo].[tbLocalizedPropertyForRevision]([LocalizedPropertyID])
GO

Para SQL Server 2016 en adelante echad un vistazo a este procedimiento que ya incluye la creación de indices.

Salir de la versión móvil