Eine Datenbank dauerhaft trennen


10

Wenn eine Datenbank dauerhaft von einer Instanz getrennt ist, sollten Bereinigungsaufgaben ausgeführt werden?


1
Können Sie den Anwendungsfall für das dauerhafte Trennen einer Datenbank erläutern? Warum nicht einfach fallen lassen?
Joe Obbish

Antworten:


13

Wenn Sie eine Datenbank von einer Instanz trennen, müssen Sie die Datei auf Betriebssystemebene löschen. Der sicherere Ansatz besteht darin, stattdessen die Datenbank zu löschen.

Ich schlage vor, eine endgültige Sicherung der Datenbank zu erstellen, nachdem Sie sie in den schreibgeschützten Modus versetzt haben (da dadurch sichergestellt wird, dass während der Sicherung keine Aktivität stattfindet). Anschließend entfernen Sie sie mithilfe eines Befehls " Datenbank löschen" von Ihrem System .

Der vollständige Befehlssatz würde wie folgt aussehen:

-- 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

Danach möchten Sie nach Jobs suchen, die Skripts für die Datenbank ausgeführt haben. Ich würde vorschlagen, dass Sie nur abwarten, was fehlschlägt (danach können Sie den Job ausschreiben / löschen), da es zahlreiche Möglichkeiten gibt, wie ein Job auf eine Datenbank verweisen kann (von denen nicht alle leicht zu identifizieren sind).

Schließlich möchten Sie alle Benutzer aus der Instanz entfernen, die nur Zugriff auf diese Datenbank hatten. Dieses Skript sollte identifizieren, wer diese Benutzer sind, obwohl Max 'Version viel sauberer ist (ich habe nicht bemerkt, dass er einen Ansatz veröffentlicht hat, bis ich meine Antwort so bearbeitet habe, dass er diesen enthält):

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

13

Ich habe Johns Antwort positiv bewertet. Ich möchte nur einige Details zu anderen Elementen hinzufügen, die Sie möglicherweise bereinigen möchten.

  1. SQL Server Agent-Jobs und -Warnungen verweisen möglicherweise auf die Datenbank. Durch das Aufräumen werden unnötige Fehler vermieden.

  2. Entfernen Sie alle Anmeldungen, die speziell für die Datenbank erstellt wurden. Das folgende T-SQL identifiziert mögliche Kandidatenanmeldungen , die Sie möglicherweise untersuchen, um festzustellen , ob sie verwendet werden. Der Code identifiziert Anmeldungen, auf die von keiner Datenbank verwiesen wird.

    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. Für diese Datenbank sind möglicherweise Sicherungsgeräte vorhanden. Obwohl das Entfernen nicht unbedingt erforderlich ist, sollten sie, wenn sie nicht verwendet werden, potenzielle zukünftige Verwirrung beseitigen.

  4. Trigger auf Serverebene können auf die Datenbank verweisen.

  5. Suchen Sie nach Wartungsplänen, die auf die Datenbank verweisen. Diese schlagen fehl, wenn sie nicht aktualisiert werden, um die fehlende Datenbank zu entfernen.


Auch die Betriebssystemdateien aus der DB sind noch vorhanden. Keine Auswirkungen auf die SQL Server-Umgebung, aber sie müssen möglicherweise gelöscht oder archiviert werden, um Speicherplatz freizugeben
CaM

@CaM: Das wurde durch Johns Antwort erklärt. Johns Vorschlag ist, die Datenbank zu löschen, anstatt sie zu trennen. Wenn Sie eine Datenbank in SQL Server löschen, werden die DB-Dateien aus dem Dateisystem gelöscht.
Andriy M

1

Alle wichtigen Punkte wurden bereits behandelt. Unten sind meine 2 Cent:

Das Trennen einer Datenbank ist niemals eine dauerhafte Lösung, da sie zum Verschieben der Datenbankdateien innerhalb des Servers oder auf einen anderen Server verwendet werden sollte. Das dauerhafte Entfernen einer Datenbank kann durch die Option Löschen in SSMS oder den Befehl DROP-Datenbank wie oben erwähnt erfolgen.

Normalerweise werden die Datenbanken, die absichtlich offline gehalten werden und weiterhin Warnungen generieren, von uns getrennt und aufbewahrt, bis sie dauerhaft entfernt (gelöscht) werden können.

Aufgabe vor dem Trennen: Führen Sie diese aus sp_helpdb dbname, um die Speicherorte der Dateien zu ermitteln.

Bereinigungsaufgaben:

  1. Löschen Sie die Dateien mdf, ndf und ldf der Datenbank an den Speicherorten, an denen sie sich befinden.
  2. Alte Sicherungsdateien für die Datenbank müssen entweder gelöscht oder unter Berücksichtigung Ihrer Aufbewahrungsdauer auf einen anderen Server verschoben werden.

Neben Anmeldungen, Agentenjobs, Triggern und bereits erwähnten Punkten von Max können diese beiden auch betrachtet werden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.