Desanexando um banco de dados permanentemente

10

Se um banco de dados for desanexado de uma instância permanentemente, existem tarefas de limpeza que devem ser feitas?

cspell
fonte
11
Você pode explicar o caso de uso para desanexar um banco de dados permanentemente? Por que não simplesmente largar?
Joe Obbish

Respostas:

13

Se você desanexar um banco de dados de uma instância, precisará executar uma exclusão do arquivo no nível do SO. A abordagem mais segura é descartar o banco de dados.

O que eu sugiro é fazer um backup final do banco de dados depois de colocá-lo no modo Somente Leitura (pois isso garantirá que nenhuma atividade esteja ocorrendo durante o backup) e, em seguida, remova-o do seu sistema por meio de um comando Drop Database .

O conjunto completo de comandos seria semelhante ao seguinte:

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

Depois disso, você desejará procurar os Trabalhos que executaram scripts no banco de dados. Eu sugiro que você apenas espere para ver o que falha (após o qual você pode criar um script / excluir o trabalho), pois há várias maneiras pelas quais um trabalho pode fazer referência a um banco de dados (nem todos são fáceis de identificar).

Por fim, convém remover todos os usuários da instância que só tiveram acesso a esse banco de dados. Esse script deve identificar quem são esses usuários, embora a versão de Max seja muito mais limpa (eu não percebi que ele postou uma abordagem até depois que eu editei minha resposta para incluir isso):

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

Eu votei na resposta de John; Gostaria de adicionar alguns detalhes sobre outros itens que talvez você queira limpar.

  1. Os trabalhos e alertas do SQL Server Agent podem fazer referência ao banco de dados. Limpá-los evitará que erros desnecessários sejam relatados.

  2. Remova todos os logons criados especificamente para o banco de dados. O T-SQL a seguir identificará possíveis logins candidatos que você pode investigar para ver se eles estão sendo usados. O código identifica logons que não são referenciados por nenhum banco de dados.

    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. Podem existir dispositivos de backup para esse banco de dados. Embora não seja estritamente necessário removê-los, se eles não estiverem sendo usados, eles devem eliminar possíveis confusões futuras.

  4. Os gatilhos no nível do servidor podem fazer referência ao banco de dados.

  5. Procure planos de manutenção que façam referência ao banco de dados - eles falharão se não forem atualizados para remover o banco de dados ausente.

Max Vernon
fonte
Além disso, os arquivos do sistema operacional do banco de dados ainda estão lá. Nenhum impacto para o ambiente do servidor SQL, mas eles podem precisar de ser excluído ou arquivado para liberar espaço em disco
CaM
@ CaM: Isso foi explicado pela resposta de John. A sugestão de John é descartar o banco de dados em vez de desanexá-lo. Soltar um banco de dados no SQL Server significa excluir os arquivos de banco de dados do sistema de arquivos.
Andriy M
1

Todos os principais pontos já foram abordados. Abaixo estão os meus 2 centavos:

A desanexação de um banco de dados nunca é uma solução permanente, pois foi projetada para ser usada para mover os arquivos de banco de dados no servidor ou para outro servidor. A remoção permanente de um banco de dados pode ser feita pela opção Excluir no SSMS ou no comando DROP database, conforme mencionado acima.

Normalmente, os bancos de dados que são intencionalmente mantidos offline e continuam gerando alertas são os que desanexamos e mantemos até que possam ser permanentemente removidos (excluídos).

Tarefa de pré-desanexação: Execute sp_helpdb dbnamepara conhecer os locais dos arquivos.

Tarefas de limpeza:

  1. Exclua os arquivos mdf, ndf e ldf do banco de dados dos locais em que residem.
  2. Os arquivos de backup antigos do banco de dados precisam ser excluídos ou movidos para outro servidor, considerando o período de retenção.

Além de logins, trabalhos de agente, gatilhos e pontos já mencionados por Max, esses dois também podem ser vistos.

Ramakant Dadhichi
fonte