2009-09-19 3 views
5

Je dois supprimer un tas de données et ne dispose pas de l'espace disque pour que le journal continue à croître. En regardant plus loin, on dirait qu'il n'y a aucun moyen de contourner cela, mais je pensais que je demanderais avec certitude; il m'est difficile de croire que quelque chose d'aussi simple est impossible.Il doit y avoir un moyen de supprimer des données dans SQL Server sans surcharger le journal

J'ai essayé de boucler, de supprimer des segments et d'appeler shrinkfile sur le journal après chaque itération. SQL Server semble simplement ignorer la commande shrinkfile. A fait la même chose avec le journal de sauvegarde (puis en supprimant le fichier de sauvegarde par la suite). Même chose - le journal ne cesse de croître. Le modèle de récupération sur la base de données que j'essaie est simple - je pensais que cela faciliterait la tâche, mais ce n'est pas le cas.

+0

Comment avez-vous essayé de réduire le journal au cours de votre stratégie « suppression en morceaux » ? Quelles étaient les commandes exactes? –

+0

dbcc shrinkfile ('log_file_name', 0) - Fonctionne bien en dehors du script – dudeNumber4

+0

Effacez-vous des informations persistantes? Ou une table temporaire pourrait-elle répondre aux besoins de stockage de ce paquet de données? – pascal

Répondre

14

Ne le supprimer en morceaux, mais plutôt que d'essayer de réduire le journal entre les temps, enregistrons des sauvegardes entre les morceaux (qui est si vous êtes en pleine récupération)

Le problème est que le journal est plein et doit donc grandir. S'il est plein, essayer de le réduire est inutile, il n'y a pas d'espace libre dans le journal pour le lancer sur le système d'exploitation. Ce que vous devez faire à la place, c'est rendre l'espace disponible dans le fichier pour le réutiliser.

Étant donné que la base de données est en mode de récupération simple, exécutez la suppression en segments avec une commande CHECKPOINT entre chaque segment. Vous ne pouvez pas faire des sauvegardes de journal en récupération simple

Voici un exemple de code qui supprime sans remplir le journal (en récupération simple). N'enveloppez PAS ceci dans une transaction personnalisée. Cela supprime complètement le point de suppression en lots car le journal ne peut pas être effacé tant que la transaction entière ne l'a pas été.

(SQL 2005 et supérieur.Pour SQL 2000, supprimez TOP et l'utilisation SET ROWCOUNT)

DECLARE @Done BIT 
SET @Done = 0 
WHILE @Done = 0 
    BEGIN 
    DELETE TOP (20000) -- reduce if log still growing 
     FROM SomeTable WHERE SomeColumn = SomeValue 
    IF @@ROWCOUNT = 0 
     SET @Done = 1 
    CHECKPOINT -- marks log space reusable in simple recovery 
    END 

Pour comprendre la gestion des journaux, jetez un oeil à cet article - http://www.sqlservercentral.com/articles/64582/

+0

Quand je lis les docs sur CHECKPOINT, cela indique que ceci se produit sur une sauvegarde de journal avec TRUNCATE_ONLY. Le journal de sauvegarde 'db_name' avec TRUNCATE_ONLY a le même effet - squat. Donc, tout (y compris les instructions du journal de sauvegarde) est enroulé en une transaction gigantesque qui est inutile dans mon cas. J'ai besoin de l'effet d'exécuter la commande 'go' sans perdre le contexte de ma boucle (je ne peux pas 'aller' au milieu d'une boucle). – dudeNumber4

+0

Vous n'avez pas besoin de GO au milieu de la boucle. GO n'a rien à voir avec les transactions, c'est un batch-terminator Il ne suffit pas de déclarer une transaction explicite et SQL effectuera chaque suppression dans sa propre transaction et permettra au journal d'être tronqué par la suite, par un point de contrôle – GilaMonster

+0

Pouvez-vous poster le code que vous utilisez pour 'découper' les suppressions, ainsi que les résultats de la requête suivante pour la base de données en question SELECT nom, log_reuse_wait_desc FROM sys.databases J'ai effectué ce type de suppression par lots des centaines de fois , ça peut marcher. – GilaMonster

4

Un truc que je l'ai utilisé en fonction de la taille des données Je garde contre le montant que je suis à la suppression est:

  1. sélectionner toutes les « données à conserver » dans une autre table (juste pour le stockage temporaire )

  2. tronquer la table originale

  3. insérer toutes les données de la table de stockage temporaire de retour dans le

  4. d'origine

Cela fonctionne bien si la quantité que vous conservez est inférieure à celle que vous supprimez. Une option similaire si tous les fichiers de la base de données se trouvent sur le même disque (données et journaux) et que les données à supprimer représentent environ la moitié des données, serait d'exporter les "données à conserver" dans un fichier sur un disque séparé à l'aide de l'utilitaire de ligne de commande bcp, puis tronquez et insérez à nouveau le fichier de données avec bcp.

J'ai vu les DBA mettre la base de données hors ligne, sauvegarder les journaux, désactiver la journalisation et le faire de cette façon, mais cela semble être un gros problème. :-)

+0

Eh bien, je doute que j'aie assez de place pour ça non plus puisque cela serait à peu près le même que ce que le journal devient (il faut supprimer environ la moitié des données). Si je comprends bien, avec Oracle, vous pouvez simplement dire "avec nolog" et supprimer des données. Je ne peux pas croire qu'il n'y a aucun moyen de faire quelque chose de si simple dans SQL Server. – dudeNumber4

+0

Vous avez raison, toutes les opérations sont consignées dans SQL Server. – GilaMonster

0

Si votre paramètre de récupération est défini sur Complet, vous pouvez essayer d'effectuer une sauvegarde du journal des transactions pour effacer le journal juste avant la suppression.

+0

Peut-être que je me méprends, mais même si le journal est presque vide au début du processus, il devient trop grand pendant la suppression. Le problème est que les serveurs (à la fois QA et la production) deviennent faibles sur l'espace. Nous avons décidé d'une nouvelle stratégie qui réduira considérablement la quantité de données dont nous avons besoin pour stocker, mais nous devons d'abord nous débarrasser des données historiques. – dudeNumber4

+0

Y at-il une raison pour laquelle vous ne pouvez pas définir le modèle de récupération de la base de données sur BULK LOGGED ou SIMPLE pendant la suppression, puis le réinitialiser à l'état normal par la suite? –

+0

C'est déjà simple où je cours ceci – dudeNumber4

Questions connexes