Defina o modo de recuperação simples e reduza os arquivos de log para todos os bancos de dados criados pelo usuário

8

Espero que você possa me apontar na direção certa. Eu não sou um usuário frequente de T-SQL, mas fiz algumas pesquisas no google e encontrei o script abaixo. Corrigi um pouco o script.

Eu quero que o script:

  1. Para selecionar todos os bancos de dados, exceto os bancos de dados do sistema.
  2. Para definir a recuperação como simples.
  3. Para reduzir os arquivos de log para cada banco de dados (.ldf), exceto o banco de dados do sistema

O script:

USE MASTER
declare
@isql varchar(2000),
@dbname varchar(64)

declare c1 cursor for select name from master..sysdatabases where name not in ('master','model','msdb','tempdb','ReportServer','ReportServerTempDB')
open c1
fetch next from c1 into @dbname
While @@fetch_status <> -1
    begin
    select @isql = 'ALTER DATABASE @dbname SET RECOVERY SIMPLE'
    select @isql = replace(@isql,'@dbname',@dbname)
    print @isql
    exec(@isql)
    select @isql='USE @dbname checkpoint'
    select @isql = replace(@isql,'@dbname',@dbname)
    print @isql
    exec(@isql)
    select @isql='DBCC SHRINKFILE @dbname.ldf'
    select @isql = replace(@isql,'@dbname',@dbname)
    print @isql
    exec(@isql)

    fetch next from c1 into @dbname
    end
close c1
deallocate c1
Arviddk
fonte
Porque porque porque? Além disso, o que é "a direção certa"? O script não funciona? Se sim, como? Você recebeu uma mensagem de erro? O que é isso? Provavelmente precisa de um comando USE no último bloco. Mas novamente: Por que, por que, por que?
Aaron Bertrand
Como os arquivos .ldf ocupam 70% do espaço em disco no servidor. Mas se você souber de uma maneira melhor, por favor, me esclareça. Não sei se o script funciona, não posso simplesmente executá-lo. Tenho que ter certeza de que funciona primeiro, pois é um ambiente de produção.
Arviddk
Você não tem um ambiente de desenvolvimento ou teste em que pode testar isso? Sinceramente eu não iria levar nada daqui, independentemente de quem o escreveu, e aplicá-lo à produção apenas com base nas garantias de estranhos na Internet ...
Aaron Bertrand
@Arviddk Você sabe quais são as consequências de alterar o modelo de recuperação de FULL / BULK LOGGED para SIMPLE? Se você estiver ciente, vá em frente e faça isso.
BuahahaXD
Eu só queria comentar o porquê de futuros leitores que possam estar procurando fazer a mesma coisa. Costumávamos fazer backups completos do SQL com backups de logs de transações. Desde então, passamos a usar o Dell AppAssure para fazer backups, o que nos coloca em um local onde não precisamos de backups de log de transações. Agora, temos centenas de bancos de dados em vários servidores ainda definidos como cheios de terabytes de arquivos LDF sem motivo. Isso afeta os backups / restaurações, bem como outras coisas que envolvem isso, a replicação e outras coisas.
Thorin

Respostas:

13

Use o Script para reduzir os arquivos de log de todos os bancos de dados, exceto os DBs do sistema.

USE MASTER   
GO    
SET QUOTED_IDENTIFIER ON  
GO  
SET ARITHABORT ON  
GO  

DECLARE @DBName NVARCHAR(255),@LogicalFileName NVARCHAR(255),@DBRecoveryDesc Varchar(200)  

DECLARE DatabaseList CURSOR   
FOR   
SELECT name,recovery_model_desc  
FROM sys.databases  
WHERE state_desc = 'ONLINE'  
AND is_read_only = 0  
and database_id>4  
ORDER BY name  

OPEN DatabaseList  
FETCH NEXT FROM DatabaseList INTO @DBName,@DBRecoveryDesc  
WHILE @@FETCH_STATUS = 0     
BEGIN   

SET @LogicalFileName=(SELECT top 1 name FROM sys.master_files AS mf WHERE DB_NAME(database_id)=@DBName and type_desc='LOG')  

If @DBRecoveryDesc='Full'  
Begin  
     Print('Use ['+@DBName+'] 
            GO  

           ALTER DATABASE ['+@DBName+'] SET RECOVERY SIMPLE WITH NO_WAIT
           GO   

            DBCC SHRINKFILE ('''+@LogicalFileName+''',10)  
            GO  

            ALTER DATABASE ['+@DBName+'] SET RECOVERY FULL WITH  NO_WAIT
            GO ')  
Print '----------------------------------------------------------- '  
END  

If @DBRecoveryDesc='Simple'  
Begin   
     Print('Use ['+@DBName+']  
            GO  

            DBCC SHRINKFILE ('''+@LogicalFileName+''',10)    
            GO    
 ')  
Print '----------------------------------------------------------- '

END

         FETCH NEXT FROM DatabaseList INTO @DBName,@DBRecoveryDesc
      END  
CLOSE DatabaseList  
DEALLOCATE DatabaseList
AA.SC
fonte
No começo, pensei que a execução ------...resultaria em erro, mas o destaque da sintaxe me deu uma dica sobre o que realmente aconteceria. Arrumado!
ta.speot.is
Obrigado, eu vou tentar fazer isso no nosso ambiente de dev e empurrar para prod
Thorin
Você deve adicionar "DBCC SHRINKFILE ('' '+ @ LogicalFileName +' _ Log '', 10) GO" - caso contrário, o banco de dados de log não será reduzido.
Andreas Rehm
5

Eu sempre tive tanta aversão aos cursores, que escrevi isso para entender melhor. É totalmente baseado na resposta da AA.SC (obrigado por falar nisso), apenas da maneira que eu acho. Se isso combina com o que os outros pensam, então ótimo. Observe que, depois disso, não o coloquei de volta no modo de recuperação total.

SELECT 
'--', d.name dbName, d.recovery_model, d.recovery_model_desc , mf.name LogicalFileName,
'
use [' + d.name + ']

if(' + cast(d.recovery_model as varchar(5)) + ' = 1)
BEGIN
    ALTER DATABASE ['+ d.name +'] SET RECOVERY SIMPLE WITH NO_WAIT
END
GO 
DBCC SHRINKFILE (''' + mf.name  +''',10)  
GO  
'
FROM sys.databases d
join sys.master_files mf
    on d.database_id = mf.database_id
    and mf.type_desc = 'LOG' 
WHERE d.state_desc = 'ONLINE'  
AND d.is_read_only = 0  
and d.database_id > 4 
--and d.recovery_model = 1
ORDER BY d.name 
Mark Rullo
fonte