Définissez un mode de récupération simple et réduisez les fichiers journaux pour toutes les bases de données créées par l'utilisateur

8

J'espère que vous pourrez m'orienter dans la bonne direction. Je ne suis pas un utilisateur fréquent de T-SQL, mais j'ai fait quelques recherches sur Google et j'ai trouvé le script ci-dessous. J'ai un peu corrigé le script.

Je veux que le script:

  1. Pour sélectionner toutes les bases de données, à l'exception des bases de données système.
  2. Pour définir la récupération sur simple.
  3. Pour réduire les fichiers journaux pour chaque base de données (.ldf), à l'exception de la base de données système

Le scénario:

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
la source
Pourquoi, pourquoi, pourquoi? Quelle est également la "bonne direction"? Le script ne fonctionne-t-il pas? Si c'est le cas, comment? Recevez-vous un message d'erreur? Qu'Est-ce que c'est? Besoin probablement d'une commande USE dans le dernier bloc. Mais encore une fois: pourquoi, pourquoi, pourquoi?
Aaron Bertrand
Parce que les fichiers .ldf occupent 70% de l'espace disque sur le serveur. Mais si vous connaissez un meilleur moyen, veuillez m'éclairer. Je ne sais pas si le script fonctionne, je ne peux pas l'exécuter. Je dois être sûr que cela fonctionne d'abord, car c'est un environnement de production.
Arviddk
Vous n'avez pas d'environnement de développement ou de test où vous pouvez tester cela? Franchement, je ne prendrais rien d'ici, peu importe qui l'a écrit, et je l'appliquerais à une production basée uniquement sur les assurances d'inconnus sur Internet ...
Aaron Bertrand
@Arviddk Savez-vous quelles sont les conséquences du changement du modèle de récupération de FULL / BULK LOGGED à SIMPLE? Si vous le savez, allez-y et faites-le.
BuahahaXD
Je voulais juste commenter le pourquoi des futurs lecteurs qui cherchent peut-être à faire la même chose. Nous avions l'habitude de faire des sauvegardes SQL complètes avec des sauvegardes de journaux de transactions. Depuis, nous sommes passés à l'utilisation de Dell AppAssure pour effectuer des sauvegardes, ce qui nous place dans un endroit où nous n'avons pas besoin de sauvegardes du journal des transactions. Maintenant, nous nous retrouvons avec des centaines de bases de données sur plusieurs serveurs encore définies avec plein de téraoctets de fichiers LDF sans raison. Cela affecte les sauvegardes / restaurations ainsi que d'autres éléments qui y sont associés, la réplication, etc.
Thorin

Réponses:

13

Utilisez Script pour réduire les fichiers journaux de toutes les bases de données autres que les bases de données système.

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
la source
Au début, je pensais que l'exécution ------...entraînerait une erreur, mais la mise en évidence de la syntaxe m'a donné un indice sur ce qui se passerait réellement. Soigné!
ta.speot.is
Merci, je vais essayer cela dans notre environnement de développement et pousser à prod
Thorin
Vous devez ajouter "DBCC SHRINKFILE ('' '+ @ LogicalFileName +' _ Log '', 10) GO" - sinon la base de données des journaux ne sera pas réduite.
Andreas Rehm
5

J'ai toujours eu une telle aversion pour les curseurs, que j'ai écrit cela comme je peux mieux le comprendre. C'est totalement basé sur la réponse d'AA.SC (merci en passant), juste d'une manière que je pense. Si cela correspond à ce que les autres pensent, alors tant mieux. Notez cependant que je ne l'ai pas remis en mode de récupération complète par la suite.

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