Encore plein : le stockage n’attend personne
« Le serveur est plein. » Je découvre qu’une phrase aussi courte peut changer complètement le programme d’une journée.
Mon premier réflexe est très développeur débutant : trouver le gros fichier, le supprimer et retourner au code. Ça règle l’alerte. Ça n’explique pas pourquoi le disque s’est rempli ni ce qui a déjà cessé de fonctionner. Quand un volume n’a plus de blocs libres, une application peut échouer en créant un fichier temporaire, SQL Server peut ne plus agrandir un fichier de données ou son journal, et une sauvegarde peut s’interrompre à moitié.
Il faut d’abord distinguer l’espace que Windows montre de ce que les applications gèrent. Le système de fichiers alloue des blocs à des fichiers. SQL Server place ensuite ses pages de données dans des fichiers .mdf ou .ndf et décrit chaque modification dans un journal .ldf avant de confirmer la transaction. Le journal permet de refaire une modification validée après une panne et d’annuler une transaction incomplète. Le supprimer comme un vieux fichier temporaire serait une très mauvaise façon de récupérer de l’espace.
Pour une table soupçonnée, sp_spaceused donne rapidement un ordre de grandeur :
EXEC sp_spaceused 'dbo.JournalApplication'
La taille d’une ligne seule ne raconte pas toute l’histoire : il y a les pages de 8 Ko, les index et de l’espace libre dans les pages. Une estimation simple reste utile. À 120 octets par événement et 40 000 événements par jour, le contenu brut ajoute environ 4,8 Mo par jour, donc 1,75 Go par année avant les index. Une croissance apparemment minuscule devient une date de panne prévisible.
Le journal de transactions obéit à une autre logique. En mode de récupération complète, une sauvegarde complète de la base ne suffit pas à rendre tout le journal réutilisable; il faut des sauvegardes du journal. Une transaction restée ouverte longtemps peut aussi retenir de l’espace. Réduire constamment le fichier après chaque alerte force seulement SQL Server à le réagrandir plus tard, ce qui fragmente le disque et déplace le coût au pire moment.
Je chercherais donc la cause dans cet ordre :
- mesurer l’espace libre du volume et les plus gros fichiers;
- vérifier la croissance des fichiers SQL et l’état des sauvegardes;
- trouver les tables, index, journaux applicatifs et temporaires qui grossissent;
- calculer un rythme quotidien et le nombre de jours avant le seuil critique;
- décider quoi conserver, archiver ou purger avec la personne responsable des données.
Une purge doit elle-même respecter le moteur. Effacer dix millions de lignes dans une seule transaction peut faire grossir encore le journal, garder des verrous et bloquer l’application. Des lots bornés par date sont plus faciles à reprendre :
DELETE FROM JournalApplication
WHERE DateEvenement < '2002-05-01'
AND IdJournal IN (
SELECT TOP 1000 IdJournal
FROM JournalApplication
WHERE DateEvenement < '2002-05-01'
ORDER BY IdJournal
)
La syntaxe exacte peut évoluer selon la version, mais le principe reste : petit lot, transaction courte, nombre de lignes journalisé, puis répétition contrôlée. Une contrainte de conservation doit venir du besoin de support, d’audit ou de loi, pas de mon envie de libérer 500 Mo cet après-midi.
Les sauvegardes ont aussi une date de sortie et une destination différente de la source. Si elles restent sur le même disque, la panne de ce disque enlève les données et leur copie. Une rotation peut garder plusieurs sauvegardes récentes sur place pour une restauration rapide et déplacer des copies vers un autre support. Le vrai test n’est pas « le fichier .bak existe », mais « on l’a restauré sur une autre instance et vérifié ».
Je vais maintenant traiter chaque fonction qui écrit sans fin comme deux fonctions : produire et expirer. J’ajouterais un compteur d’espace libre avec des seuils assez tôt pour agir, pas une alerte au dernier mégaoctet. Ajouter un disque peut donner du temps; mesurer la croissance, tester les restaurations et automatiser une rétention donnent une vraie sortie au problème.