Separar una base de datos de forma permanente

10

Si una base de datos se separa de una instancia de forma permanente, ¿hay alguna tarea de limpieza que deba hacerse?

cspell
fuente
1
¿Puede explicar el caso de uso para separar una base de datos de forma permanente? ¿Por qué no simplemente dejarlo caer?
Joe Obbish

Respuestas:

13

Si separa una base de datos de una instancia, deberá realizar una eliminación del archivo a nivel del sistema operativo. El enfoque más seguro es descartar la base de datos.

Lo que sugiero es tomar una copia de seguridad final de la base de datos después de ponerla en modo de solo lectura (ya que esto asegurará que no se produzca actividad durante la copia de seguridad), después de lo cual elimínela de su sistema mediante un comando Soltar base de datos .

El conjunto completo de comandos sería similar al siguiente:

-- Use master db to ensure you don't have an active connection to the db you wish to affect
USE [master]
GO

-- This will kill any active transactions, but will force the database into a Read-Only state
ALTER DATABASE [db_name] SET READ_ONLY WITH ROLLBACK IMMEDIATE
GO

BACKUP DATABASE [db_name] -- Fill in more options here or use the UI to take a backup if you chooose
GO

-- This will kick out all connections from the database allowing you to drop it.
ALTER DATABASE [db_name] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO

-- Drop the database (which automatically removes the files from the OS)
DROP DATABASE [db_name]
GO

Después de esto, querrá buscar cualquier trabajo que ejecute scripts en la base de datos. Le sugeriría que espere para ver qué falla (después de lo cual puede eliminar / borrar el trabajo) ya que hay muchas formas en que un trabajo puede hacer referencia a una base de datos (no todas son fáciles de identificar).

Finalmente, querrá eliminar a los usuarios de la instancia que solo tenían acceso a esta base de datos. Este script debe identificar quiénes son esos usuarios, aunque la versión de Max es mucho más limpia (no me di cuenta de que publicó un enfoque hasta después de editar mi respuesta para incluir esto):

DECLARE @ExecString NVARCHAR (4000)

-- Create Empty Table in a very lazy manner
SELECT  name, principal_id, CAST('' AS NVARCHAR(128)) as database_name
INTO ##tmp_AllDBUsers
FROM sys.server_principals
WHERE 1 = 2

-- Declare Cursor to iterate through all DBs on the instance
DECLARE dbCursor CURSOR
FOR
        SELECT name
        FROM sys .databases


DECLARE @name NVARCHAR (128)
OPEN dbCursor
FETCH NEXT FROM dbCursor
INTO @name

WHILE @@FETCH_STATUS = 0
BEGIN

    SET @ExecString = 
    'USE [' + @name + '];
    INSERT INTO ##tmp_AllDBUsers
    SELECT sp.name, sp.principal_id, DB_NAME()
    FROM sys.server_principals sp INNER JOIN sys.database_principals dp
        ON sp.sid = dp.sid'

    EXEC(@ExecString)

    FETCH NEXT FROM dbCursor
    INTO @name
END

-- Close and deallocate the cursor because you've finished traversing all it's data
CLOSE dbCursor
DEALLOCATE dbCursor

-- Show all logins that do not belong to a server-level role nor have access to any databases
SELECT sp.*
FROM sys.server_principals sp LEFT JOIN ##tmp_AllDBUsers adu
    ON sp.principal_id = adu.principal_id
WHERE adu.principal_id IS NULL
    AND sp.principal_id NOT IN (SELECT member_principal_id
                            FROM sys.server_role_members)
    AND TYPE IN ('S', 'U', 'G')

-- cleanup
DROP TABLE ##tmp_AllDBUsers
John Eisbrener
fuente
13

He votado a favor la respuesta de John; Solo me gustaría agregar algunos detalles sobre otros elementos que tal vez desee limpiar.

  1. Los trabajos y alertas del Agente SQL Server pueden hacer referencia a la base de datos. Limpiarlos evitará que se reporten errores innecesarios.

  2. Elimine los inicios de sesión creados específicamente para la base de datos. El siguiente T-SQL identificará posibles inicios de sesión de candidatos que puede investigar para ver si se están utilizando. El código identifica inicios de sesión a los que ninguna base de datos hace referencia.

    DECLARE @cmd nvarchar(max);
    SET @cmd = '    SELECT sp.sid
        FROM master.sys.server_principals sp
    ';
    SELECT @cmd = @cmd + '  EXCEPT 
        SELECT dp.sid
        FROM ' + QUOTENAME(d.name) + '.sys.database_principals dp
    '
    FROM sys.databases d
    WHERE d.[state] <> 6; --ignore offline DBs
    
    SET @cmd = 'SELECT spr.*
    FROM (
    ' + @cmd + '
    ) src
        INNER JOIN master.sys.server_principals spr
            ON src.sid = spr.sid
    WHERE spr.type <> ''R''
        AND spr.name NOT LIKE ''%##MS_%''
        AND spr.name NOT LIKE ''NT %''
        AND NOT EXISTS (
            SELECT 1
            FROM sys.server_role_members srm
            WHERE srm.member_principal_id = spr.principal_id
                )
    ORDER BY spr.name;
    ';
    EXEC sys.sp_executesql @cmd;
    
  3. Pueden existir dispositivos de respaldo para esa base de datos. Si bien eliminarlos no es estrictamente necesario, si no se usan, deberían eliminar la posible confusión futura.

  4. Los desencadenantes a nivel de servidor pueden hacer referencia a la base de datos.

  5. Busque planes de mantenimiento que hagan referencia a la base de datos; estos fallarán si no se actualizan para eliminar la base de datos que falta.

Max Vernon
fuente
También los archivos del sistema operativo de la base de datos todavía están allí. Sin impacto en el entorno del servidor SQL, pero es posible que necesiten ser eliminados o archivados para liberar espacio en disco
CaM
@CaM: Eso ha sido explicado por la respuesta de John. La sugerencia de John es eliminar la base de datos en lugar de separarla, y eliminar una base de datos en SQL Server significa eliminar los archivos de base de datos del sistema de archivos.
Andriy M
1

Todos los puntos principales ya han sido cubiertos. A continuación están mis 2 centavos:

Separar una base de datos nunca es una solución permanente, ya que estaba destinado a usarse para mover los archivos de la base de datos dentro del servidor o a otro servidor. La eliminación de una base de datos de forma permanente se puede hacer mediante la opción Eliminar en SSMS o el comando de base de datos DROP como se mencionó anteriormente.

Por lo general, las bases de datos que se mantienen intencionalmente fuera de línea y siguen generando Alertas son las que separamos y mantenemos hasta que se puedan eliminar de forma permanente (Eliminado).

Tarea previa a la separación: Ejecute sp_helpdb dbnamepara conocer las ubicaciones de los archivos.

Tareas de limpieza:

  1. Elimine los archivos mdf, ndf y ldf de la base de datos de las ubicaciones donde residen.
  2. Los archivos de respaldo antiguos para la base de datos deben ser eliminados o trasladados a otro servidor teniendo en cuenta su período de retención.

Además de Logins, Agent Jobs, Triggers y puntos ya mencionados por Max, estos 2 también se pueden considerar.

Ramakant Dadhichi
fuente