web-dev-qa-db-fra.com

Comment réparer la corruption pour «possible problème de liaison de chaîne».

J'ai une grande table avec 15 000 000 d'enregistrements et soudainement Select Top a cessé de fonctionner. J'utilise MS SQL Management Studio.

Cela ne fonctionne pas, la requête renvoie 0 enregistrements:

SELECT TOP (10) 
       [Id]
      ,[Result]
      ,[DateStamp]
      ,[ConversionTime]
      ,[Converter]
      ,[SourceFileFormat]
      ,[DestinationFileFormat]
      ,[Ip]
      ,[Source]
      ,[Error]
      ,[UserId]
      ,[TokenId]
      ,[ConversionCost]
  FROM [ca-v2].[dbo].[Log]

À ma grande surprise, si j'essaie de sélectionner un champ ID, cela fonctionne en pourcentage.

Fonctionne bien:

SELECT TOP (10) 
       [Id]        
  FROM [ca-v2].[dbo].[Log]

De plus, si j'ajoute une commande à la fin, la requête commence également à fonctionner:

SELECT TOP (10) 
       [Id]
      ,[Result]
      ,[DateStamp]
      ,[ConversionTime]
      ,[Converter]
      ,[SourceFileFormat]
      ,[DestinationFileFormat]
      ,[Ip]
      ,[Source]
      ,[Error]
      ,[UserId]
      ,[TokenId]
      ,[ConversionCost]
  FROM [ca-v2].[dbo].[Log]
  Order By [DateStamp]

L'Iran DBCC CHECKTABLE sur la table et a reçu l'erreur suivante:

Erreur: Msg 8978, niveau 16, état 1, ligne 1

Erreur de table: ID d'objet 1029578706, ID d'index 1, ID de partition 72057594043367424, ID d'unité d'allocation 72057594045071360 (type Données en ligne). La page (1: 5044) manque une référence de la page précédente (1: 5042). Problème de liaison de chaîne possible.

Que puis-je faire à ce sujet?

Avec l'aide de @RDFozz, j'ai pu réparer l'index endommagé à l'aide de sql

ALTER DATABASE "db" SET SINGLE_USER WITH ROLLBACK IMMEDIATE

go

DBCC CheckTable ("log", REPAIR_REBUILD) 

go

ALTER DATABASE "db" SET MULTI_USER WITH ROLLBACK IMMEDIATE

Deux choses importantes ici: 1) une base de données doit être mise en mode mono-utilisateur. 2) si la base de données est en production et a d'autres connexions, la commande utilisateur SET doit être obtenue avec ROLLBACK IMMEDIATE pour supprimer les connexions actuelles.

5
Tomas

Lorsque vous êtes confronté à une corruption de base de données, vous devrez déterminer l'étendue du problème. Avez-vous une table/un index corrompu, ou plusieurs? Vous voudrez probablement exécuter DBCC CHECKDB sur la base de données.

Selon ce que vous trouvez, vous disposez des options suivantes (par ordre décroissant de sécurité):

  1. Restaurer à partir d'une sauvegarde

    Il s'agit généralement de la solution la plus simple et la plus sûre. Cependant, si vous n'êtes pas certain de la date à laquelle la corruption est apparue, cela peut ne pas être pratique - il est possible que vous n'ayez aucune sauvegarde récente sans la corruption. Et, selon l'utilisation de la base de données, jeter une journée de données pour corriger la corruption pourrait être très coûteux, en termes de continuer à être en mesure de gérer votre entreprise.

    Cependant, si la corruption est grave, cela peut être la seule solution dont vous disposez. Même si vous essayez certaines des options suivantes, vous devrez peut-être revenir à celle-ci.

    Si vous avez des sauvegardes, gardez-les à portée de main et n'en faites pas de cycle (si possible) avant d'avoir résolu le problème.

  2. Utilisation DBCC CHECKTABLE ou DBCC CHECKDB avec une option de réparation

    Votre série de DBCC CHECKTABLE et/ou DBCC CHECKDB peut avoir indiqué une option de réparation que vous pourriez utiliser pour essayer de restaurer les choses à la normale.

    Les commandes ont les mêmes options de réparation:

    • REPAIR_FAST - comme il est dit, il a essayé des choses simples et prendra moins de temps que les autres options de réparation. Comme vous pouvez le deviner, cela signifie également qu'il est le moins susceptible de réussir.

    • REPAIR_REBUILD - Cela fait ce que REPAIR_FAST le fait, mais est également prêt à essayer de reconstruire des index à partir de zéro - du problème est dans un index non clusterisé, cela devrait le résoudre.

    • REPAIR_ALLOW_DATA_LOSS - Comme indiqué, il essaiera de restaurer la convivialité des objets affectés, mais devra peut-être éliminer les lignes partielles et ainsi de suite; vous risquez de perdre certaines de vos données. C'est l'une des raisons pour lesquelles la restauration d'une sauvegarde est souvent la meilleure solution.

  3. Frankensteining votre mauvaise table (pour ainsi dire)

    Si seul ce tableau est affecté, vous pouvez essayer de:

    • Recherchez une sauvegarde dans laquelle la table n'est pas corrompue (et placez la sauvegarde sous un nom différent);
    • Laissez tomber la mauvaise table;
    • Confirmez que cela n'a pas déplacé votre problème ailleurs en exécutant DBCC CHECKDB encore; et
    • Copiez dans le tableau et ses données depuis la sauvegarde.


    Ou, pour essayer de conserver autant de données les plus récentes que possible:

    • Préparez une sauvegarde, comme ci-dessus
    • Utilisation REPAIR_ALLOW_DATA_LOSS sur la table.
    • Si la table fonctionne maintenant, recherchez les lignes de la sauvegarde qui ne figurent pas dans la table réparée et copiez-les.

Comme indiqué par CaM dans les commentaires, vous devez l'utiliser comme motivation pour vous assurer que vous effectuez des tâches de maintenance régulières sur votre base de données.

Tout d'abord, si vous n'êtes pas aujourd'hui, commencez à le sauvegarder régulièrement. La plupart des bases de données que j'administre ont une sauvegarde complète hebdomadaire et des sauvegardes différentielles quotidiennes, nous ne devons donc jamais perdre plus d'une journée de données.

En outre, vous devez exécuter DBCC CHECKDB régulièrement pour détecter la corruption avant qu'elle ne devienne trop grave pour être corrigée. C'est aussi quelque chose que j'essaie d'exécuter chaque semaine.

11
RDFozz