Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

SQL Server : Comment forcer le Shrink du journal de transaction?

J'avais déjà abordé ce sujet précédemment :

http://blogs.codes-sources.com/christian/archive/2007/02/12/sql-server-faq-sql-pourquoi-mon-fichier-de-log-ldf-est-il-aussi-gros-comment-diminuer-sa-taille.aspx

Mais je me suis rendu compte au fil du temps que la réduction de la taille du journal de transaction en fonctionnait pas du premier coup.

En regardant de plus près le fonctionnant de celui-ci c'est normal. La figure ci-dessous represente un fichier LDF contenant le journal de transaction d'une base de données SQL Server. Chaque case est appelé VLF (Virtual Log File).

X

X

X

X

X

X

X

A

Où :

  • X est un VLF rempli
  • A est le VLF actif

Un VLF n'est pas un fichier, c'est une zone de stockage dans le ou les fichiers de journaux de transaction d'une base de données (extension généralement LDF), ils sont de taille différentes, même au sein d'un même fichier.

En effet le journal (basiquement le fichier LDF) se rempli de manière séquentiel, c'est donc quand le fichier est rempli la partie finale qui est la portion courante du journal. Or il n'est pas possible d'exécuter de Shrink (opération de réduction du fichier) si justement la portion finale est active.

Alors comment faire ? Il faut « forcer » le moteur à utiliser une autre portion, idéalement située au début du journal. Seulement le fichier est rempli à cet endroit il n'esdt donc pas possible pour SQL Server d'utiliser cette portion.

X

X

X

X

X

X

X

A

 

On va donc vider le journal, cette opération se fait grâce à la commande BACKUP LOG :

BACKUP LOG MaBase TO DISK = 'C:\...'

OU de manière moins conseillée, on tronque le journal avec une variante de la même commande :

BACKUP LOG MaBase WITH TRUNCATE_ONLY

Le résultat dans le journal de transaction est le suivant :

             

A

 

La portion active est toujours situé à la fin (sauf cas exceptionnel, en effet il est tout à fait possible que la portion active se deplace faute de place et à cause de transactions en cours), mais le début du fichier est maintenant vide et peut être réutilisé.

Il faut donc une méthode pour que le moteur de base de données change la portion active. Cela est possible (à condition qu'aucune transaction ne soit en cours) avec :

CHECKPOINT

Le résultat sera :

A

           

X

Le shrink dans ce cas n'est toujours pas possible, en effet la portion active est au début du fichier, mais la fin est occupé par des informations du journal non sauvegardé ou non tronqué… On repasse une commande de sauvegarde du journal :

BACKUP LOG MaBase TO DISK = 'C:\...'

-- ou --

BACKUP LOG MaBase WITH TRUNCATE_ONLY

 

On obtient :

A

             

 

Et cette fois ci il est normalement possible de réaliser l'opération souhaité par :

DBCC SHRINKFILE (2)

Le numéro 2, correspond au journal de transaction (ou du moins le 1er fichier s'il y en avait plusieurs).

A

     

 

Attention le moteur ne supprime jamais tous les VLF du journal de transaction, en fonction de la taille initiale du journal, des incréments de taille de fichier, leur nombre pourra varier, il n'y en aura cependant jamais moins que 4 et vous ne pourrez pas contrôler leur taille à postériori !

Si la succession des opérations précédentes échoue, vous n'aurez qu'à renouveler les opérations à plusieurs reprises.

BACKUP LOG MaBase -- TO DISK = 'C:\...' ou WITH TRUNCATE_ONLY

CHECKPOINT

BACKUP LOG MaBase -- TO DISK = 'C:\...' ou WITH TRUNCATE_ONLY

DBCC SHRINKFILE (2)

-- Si echec on retente...

CHECKPOINT

BACKUP LOG MaBase -- TO DISK = 'C:\...' ou WITH TRUNCATE_ONLY

DBCC SHRINKFILE (2)

 

Cela peut paraitre un peu fastidieux, et limite archaïque, le problème étant qu'il est difficile de prévoir le fait que vous ayez ou non une transaction active qui bloque le recyclage du journal. Si vous n'y arrivez, pas attendez 5 min et réessayer sinon, vérifier les sessions actuelles, et prenez attention à celles exécutant une requête.

Cette méthode fonctionne dans plus de 99% des cas où je l'ai testé et elle est très pratique. Il est cependant possible qu'elle ne fonctionne pas quelques cas rares, hors ceux évoqués plus haut :

  • Replication transactionelle bloquant la vidange du journal
  • Change Data Capture bloquant la vidange du journal
  • Plus d'espace disponible sur le disque où se situe le LDF et/ou MDF (nécessite alors d'ajouter un fichier LDF sur une autre unité)
  • Backup Log en cours
  • Database Mirrroring en cours de synchronisation
Tous ces cas peuvent bloquer plus ou moins longtemps une portions des VLF du journal, vérifiez bien ce qui est en cours d'execution sur votre base de données et sa configuration !

Après la réduction de la taille du journal, si possible augmentez manuellement la taille de celui-ci.

ALTER DATABASE MaBase MODIFY FILE (name = 'nom logique', SIZE = 2GB)

Cela évitera de fragmenter inutilement le journal de transaction et le moteur de base de données ne s'en trouvera que plus efficace pour toutes écriture et transactions à effectuer dans la base de données.

Bonne réduction…

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :
Publié lundi 14 décembre 2009 21:50 par christian
Classé sous : ,

Commentaires

vendredi 25 décembre 2009 23:17 by Maveric

# re: SQL Server : Comment forcer le Shrink du journal de transaction?

J'ai souvent ce probleme de non fonctionnement du 1er coup mais 9 fois sur 10 en relancant une seconde fois c'est Ok et ceux sans executer le checkpoint. Normal ?

Sinon j'en profite pour te demander conseil. Je suis embêté avec un ensemble de requete de suppression dans une procedure stockée qui me genere un fichier de log enorme au point de ne pas avoir assez de place (J'ai sous estimé la taille du disque stockant la partie log je l'avoue 40Go).

Bref ces delete suppriment quelques millions de lignes dans des tables qui en comportent des dizaines de millions.

Je suis en mode de recuperation "journalisé en bloc". J'ai essayé une solution du type suivant :

SET ROWCOUNT 500;

delete_data:

DELETE FROM INFO_CONTACT

WHERE IdFichier = @IdFichier;

IF @@ROWCOUNT >0

GOTO delete_data;

mais cette fois c'est le delai d'execution qui a explosé( plus de 15h00 apres je l'ai arreté)

Bref je ne sais plus quoi faire

Si tu as une idée je suis preneur car la je ne sais plus quoi faire !!!

Maveric

mardi 29 décembre 2009 16:12 by Mimetis

# re: SQL Server : Comment forcer le Shrink du journal de transaction?

T'as une solution plutôt simple, mais qui risque de te demander des concessions :)

Tu peux par exemple, avant d'effectuer ton delete, passer ta base en mode de recouvrement simple et la repasser en mode Complet aprés.

Par contre ça va te "casser" la chaine de récupération. Il vaudrait mieux alors après avoir effectuer cette manipulation faire une sauvegarde complète de ta base; au cas où...

Seb

mardi 29 décembre 2009 16:40 by christian

# re: SQL Server : Comment forcer le Shrink du journal de transaction?

@Maveric : Pour le 9 / 10, c'est à peu près mes observation... sans le Checkpoint c'est possible que celà fonctionne, perso je préfère le mettre quand même car il m'assure une écriture dans le journal (marque de Début du Checkpoint et de fin du Checkpoint). En plus s'il y a eu Truncate, celà m'assure aussi que quasiement toutes les données sont écritures dans les fichiers de données, certes celà peut être long.

Idéalement pour supprimer de grande quantités : TRUNCATE TABLE (je sais il n'y a pas de WHERE, et quelques limites). Sinon par batch essaye d'augmenter le nombre 5000 est peut être un peu bas, il faut que le DELETE tiennent en mémoire... Par contre je parirais que tout sera inscrit tout de même dans le journal de transaction, donc même resultat. Peut être en supprimant les index puis les données (si c'est possible). En réalisant des BACKUP LOG pendant la suppression par bloc (comme dit avant + de 5000), mais çà revient à la méthode de Mimetis, de passer en mode journalisation simple (sans les désavantages).

Si c'est du SQL 2005 Enterprise en partitionnant la table on peut ruser un peu aussi.

@Mimetis : Je ne dirais pas "il vaudrais mieux", mais "il faut"... Pourquoi, parce que si on passe en mode simple ou si on réalise un TRUNCATE du log, la base de données reste en mode de récupération simple tant qu'une sauvegarde complète n'est pas executée.

samedi 2 janvier 2010 12:17 by Maveric

# re: SQL Server : Comment forcer le Shrink du journal de transaction?

Merci a tous les deux pour vos éléments de reponse.

@Mimetis : J'avais éliminé la solution du mode de récupération simple car  pour moi seules les opération d'importations en bloc (bcp,bulk insert...) et les opérations de type select into etaient journalisées au minimum. Cela ne changerait donc rien a la croissance importante du fichier de log. Je n'ai pas essayé, je suis donc peut etre dans le faux.

@Christian : Ok pour le checkpoint, je l'ai du coup ajouté a mes scripts de maintenance.

J'ai suivi tes recommandations en augmentant la taille mais c'est surtout la desactivation des index qui m'a fait gagné enormement de taille.

Merci encore a tous deux pour vos conseils et une bonne année 2010.

Maveric

Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Comment mapper une vue SQL sur une collection de complex type? par Matthieu MEZIL le il y a 13 heures et 39 minutes

- SQL Server : Query Notification ou comment être notifié de modifications de données côté application (SqlDependency) par SQL Server vu par Christian Robert le il y a 19 heures et 38 minutes

- [WF4] Un Binding Activity/ActivityDesigner qui passe mal? par Blog de Jérémy Jeanson le il y a 21 heures et 1 minutes

- MyTIC – SharePoint 2010 : déjà un mythe Microsoft ? par Le Blog (Vert) d'Arnaud JUND le 03-19-2010, 08:54

- TechDays 2010 Genève : Retrouvez-moi pour une session sur la Haute disponibilité et le ScaleOut avec SQL Server par SQL Server vu par Christian Robert le 03-18-2010, 15:45

- [MIX10] Keynote deuxième journée – Internet Explorer 9, Html5, Visual Studio 2010, OData par Atteint de JavaScriptite Aiguë [Cyril Durand] le 03-17-2010, 19:40

- Certifications beta .NET 4 par Kévin Gosse le 03-17-2010, 19:33

- [Mix 2010] – Microsoft Translator Technology Preview V2 par RedoBlog - The .NET Gentleman !!! le 03-17-2010, 18:53

- Lancement en Preview de Cyclone lors des TechDays 2010! par Blog de Frédéric Queudret le 03-17-2010, 16:30

- [WP7] Je ne veux pas d’un nouvel iPhone par Le blog de FremyCompany le 03-17-2010, 13:11