web-dev-qa-db-fra.com

Comment faire un journal unique rétrécissant sur une base de données avec une réplication transactionnelle

J'ai hérité d'une base de données de 10 Go avec un journal de 80 Go [seulement 3% d'utilisation selon DBCC SQLPERF (logspace)]. Il semble prudent de supposer que la croissance du journal extrême était due à des problèmes de longue date avant d'être embauché.

Le primaire a un travail de sauvegarde d'expédition de journal qui fonctionne toutes les 15 minutes. Le primaire a copier et restaurer des travaux qui fonctionnent toutes les 15 minutes.

Lorsque j'essaie de réduire le journal, je reçois "Impossible de réduire le fichier journal 2 (Databasename_Log) car le fichier journal logique situé à la fin du fichier est utilisé." Je l'ai réessayé plusieurs fois 15 minutes de distance et même des jours d'intervalle, mais obtenez toujours le même résultat.

DBCC Loginfo affiche 784 VLFS, avec seulement les premiers 245 et la dernière avec un statut de 2. P_WhoisActive montre que la transaction ouverte la plus longue est exécutée pendant moins de 2 heures (de longues transactions ne sont pas inhabituelles ici en raison d'une tierce partie Microsoft Application d'accès avec ODBC Problèmes de pilote).

Comment puis-je rétrécir avec succès ce journal (sans créer de panne pour les utilisateurs)?

Merci, marque

2
Mark Freeman

La solution la plus simple à ce problème consiste à définir la base de données à une simple récupération, rétrécissez le journal, puis le remettez-le à la récupération complète. Dans T-SQL, ce serait:

ALTER DATABASE [database] SET RECOVERY SIMPLE WITH NO_WAIT
DBCC SHRINKFILE([logfilename], 1)
ALTER DATABASE [database] SET RECOVERY FULL WITH NO_WAIT

Changer la base de données en une récupération simple peut entraîner une réplication des transactions, mais si elle est programmée pendant les heures d'arrêt, il devrait rétrécir le journal et revenir à la récupération complète sans effets secondaires.

Si cela est inacceptable, vous pouvez utiliser la procédure SP_REPLDONE stockée pour marquer manuellement les transactions comme distribué et réinitialiser l'état de la réplication des transactions non valides:

EXEC sp_repldone @xactid = NULL, @xact_segno = NULL, @numtrans = 0,    @time = 0, @reset = 1
7
dartonw

Vous pouvez potentiellement exécuter un script tel que celui-ci pour tenter l'opération de rétrécissement une fois par minute jusqu'à ce qu'il se termine ou fonctionne de 1 000 fois. comme toujours, utilisez vos propres risques - et testez-le d'abord sur un environnement de non-production.

USE tempdb;  /*  CHANGE THIS TO DESIRED DATABASE */
GO
DECLARE @DesiredSizeInMB INT;
SET @DesiredSizeInMB = 1;

DECLARE @T TABLE (
    CurrentSize BIGINT
);
DECLARE @LogFileName VARCHAR(255);
DECLARE @LoopCount INT;
DECLARE @MaxLoops INT;
DECLARE @OK BIT;

SELECT @LogFileName = df.name
FROM sys.database_files df
WHERE df.type_desc = 'LOG';

SET @LoopCount = 0;
SET @MaxLoops = 1000;
WHILE @LoopCount < @MaxLoops
BEGIN
    SET @OK=1;
    BEGIN TRY
        DELETE FROM @T;
        INSERT INTO @T
        SELECT size * 8192 / 1048576E0
        FROM sys.database_files df
        WHERE df.type_desc = 'LOG';
        DBCC SHRINKFILE (@LogFileName, @DesiredSizeInMB);
        /* If the now-current size of the log file is with 1MB of the target size, break */
        IF (SELECT CurrentSize * 8192 / 1048576E0 FROM @T) <= @DesiredSizeInMB + 1 
            BREAK;
        ELSE
            SET @OK = 0;
    END TRY
    BEGIN CATCH
        SET @OK=0;
        PRINT ERROR_MESSAGE();
    END CATCH
    IF @OK = 1 BREAK; /* IF the command didn't fail, then exit the loop */
    WAITFOR DELAY '00:00:30'
    SET @LoopCount = @LoopCount +1;
END
2
Max Vernon

Lors du test de mon plan de sauvegarde sur un serveur de test VM qui a été déconnecté du réseau, j'exécutions une sauvegarde, puis utilisait la commande rétractable uniquement. J'utilise un modèle de récupération simple, je devais toujours forcer le réglage de la base de données en mode simple, alors seulement je pourrais réduire mes journaux T. La conclusion semble que si vous avez une base de données dans un modèle de récupération simple, vous n'avez pas encore besoin de ces commandes: Alter la base de données [base de données] SET RÉCUPÉRATION Simple avec No_Wait DBCC Strinkfile ([LOGFILEName], 1)

0
Ryszard