KB3067257 – FIX: Teilergebnisse in einer Abfrage eines gruppierten Columnstore-Indexes in SQL Server 2014

Gilt für
SQL Server 2014 Developer - duplicate (do not use) SQL Server 2014 Enterprise - duplicate (do not use) SQL Server 2014 Standard - duplicate (do not use)

In diesem Artikel wird ein Problem behandelt, das während einer Abfrage eines gruppierten Columnstore-Indexes in Microsoft SQL Server 2014 auftritt. Dieser Artikel bietet eine Lösung für dieses Problem.

Zusammenfassung

Wenn Sie eine Abfrage verwenden, die einen gruppierten Columnstore-Index in Microsoft SQL Server 2014 scannt, erhalten Sie möglicherweise unter seltenen Bedingungen Teilabfrageergebnisse.

Dieses Problem tritt auf, wenn der folgende Vorgang ausgeführt wird.

Schritt 1

Eine Transact-SQL-Anweisung [INSERT oder BULK-INSERT] fügt Daten in eine Tabelle ein, die über einen gruppierten Columnstore-Index verfügt. Während dieses Vorgangs gelten die folgenden Bedingungen:

  • Wenn die Transact-SQL-Anweisung den Zeilengruppenschwellenwert erreicht, wird die Zeilengruppe R1 mit segment S1 geschlossen.
  • Segment S1 verweist auf das lokale Wörterbuch D1.
  • Die -Anweisung fügt weiterhin Zeilen in die neue Zeilengruppe R2 ein.
  • Wenn die Zeilengruppe R1 geschlossen wird, muss nicht auch das lokale Wörterbuch D1 geschlossen werden. Wenn im Wörterbuch D1 noch Speicherplatz verfügbar ist, können Sie es geöffnet lassen und für die neue Zeilengruppe R2 wiederverwenden.

Schritt 2

Wenn die Transact-SQL-Anweisung nicht ordnungsgemäß beendet oder abgebrochen wird, bevor sie die neue Zeilengruppe R2 schließt, gelten die folgenden Bedingungen:

  • Columnstore-Metadatenänderungen treten in Untertransaktionen auf, die unabhängig von der äußeren Transaktion committet werden.
  • An diesem Punkt bleibt die Zeilengruppe R1 in der Systemtabelle in einem Zustand "unter Konstruktion" oder "UNSICHTBAR", und Segment S1 verweist auf das Wörterbuch D1.
  • In der Systemtabelle für das Wörterbuch D1 wurde keine Zeile erstellt. Dies liegt daran, dass die Transact-SQL-Anweisung nie die Möglichkeit hat, die vorhandene Zeile zu schließen. Daher wird die vorhandene Zeile beibehalten.

Schritt 3

Wenn in einer typischen Situation die Hintergrundaufgabe tupel mover gestartet wird, nachdem die Transact-SQL-Anweisung beendet wurde, entfernt die Hintergrundaufgabe die unsichtbare Zeilengruppe R1 und das Segment S1. Wenn jetzt eine neue Transact-SQL-Anweisung gestartet wird und die Zeilengruppe R3 mit einem neuen Segment S3 erstellt wird, das ein neues lokales Wörterbuch erfordert, können Sie die interne ID des Wörterbuchs D1 nicht wiederverwenden. Dies liegt daran, dass der In-Memory-Zustand des Columnstores die verwendeten Wörterbuch-IDs nachverfolgt. Daher verweist Segment S3 auf das neue Wörterbuch D2.

Hinweis Die Bedingung in diesem Schritt ist eine häufige Bedingung. Daher tritt keine Beschädigung auf.

Schritt 4

Wenn SQL Server den In-Memory-Zustand des Wörterbuchs D1 verliert, bevor die Tupelverschiebungsaufgabe wirksam wird (und wie in Schritt 3 beschrieben ausgeführt wird), tritt das in diesem Artikel beschriebene Problem auf.

Notizen

  • Dieses Ereignis tritt aus einem der folgenden Gründe auf:

    • SQL Server Überlastung des Arbeitsspeichers, und der In-Memory-Inhalt des Wörterbuchs D1 wird aus dem Arbeitsspeicher entfernt.
    • Die instance von SQL Server wird neu gestartet.
    • Die Datenbank, die den gruppierten Columnstore-Index enthält, wird offline geschaltet und wieder online geschaltet.
  • Nachdem eines dieser Ereignisse eintritt und SQL Server die In-Memory-Strukturen erneut lädt, ist kein Datensatz vorhanden, dass ein Wörterbuch D1 und seine interne ID vorhanden waren. Dies liegt daran, dass das Wörterbuch D1 nicht in den Systemtabellen beibehalten wurde, als die Transact-SQL-Anweisung beendet oder abgeschlossen wurde.

  • Wenn die Tupelverschiebungs-Hintergrundaufgabe an diesem Punkt gestartet wird, treten keine Fehler auf, da die in Schritt 3 beschriebenen Bedingungen zutreffen.

  • Wenn eine neue Zeilengruppe R3 erstellt wird, bevor die Tupelverschiebungs-Hintergrundaufgabe gestartet wird (gemäß dem vorherigen Aufzählungszeichen), weist SQL Server dem neuen Wörterbuch D1 die gleiche interne ID zu und verweist auf Wörterbuch D1 für Segment S3 in Zeilengruppe R3.

  • Wenn die Tupelverschiebungs-Hintergrundaufgabe nach der vorherigen Aktion gestartet wird, löscht sie die unsichtbare Zeilengruppe R1 und ihre Segmente S1 zusammen mit dem neuen Wörterbuch D1. Dies liegt daran, dass der Tupel mover das neue Wörterbuch D1 und das ursprüngliche Wörterbuch D1, auf das S1 verweist, identisch sind.

    Hinweis Wenn diese Bedingung auftritt, können Sie den Inhalt der Zeilengruppe R3 nicht abfragen.

Lösung

Das Problem wurde zunächst in den folgenden kumulativen Updates für SQL Server behoben:

Kumulatives Update 1 für SQL Server 2014 SP1
        
         Kumulatives Update 8 für SQL Server 2014
Die Behebung dieses Problems ist auch in den folgenden updates für die allgemeine Distributionsversion enthalten:

Sicherheitsupdate für SQL Server 2014 QFE  
Dieses Update enthält kumulatives Update 8, diesen wichtigen Fix und die erforderlichen MS15-058-Sicherheitsupdates.

Sicherheitsupdate für SQL Server 2014 GDR  
Dieses Update enthält diesen wichtigen Fix und kumulative Sicherheitsupdates über MS15-058.

Nicht sicherheitsrelevantes Update für SQL Server 2014 Service Pack 1 GDR  
Dieses Update enthält nur diesen wichtigen Fix.

Informationen zu kumulativen Updates für SQL Server

Jedes neue kumulative Update für SQL Server enthält alle Hotfixes und alle Sicherheitsfixes, die im vorherigen kumulativen Update enthalten waren. Sehen Sie sich die neuesten kumulativen Updates für SQL Server an:

      

Weitere Informationen

FehlermeldungenIn einer aktuell betroffenen Datenbank erhalten Sie folgende Fehlermeldung, wenn Sie DBCC CHECKDB ausführen, nachdem Sie diesen Fix angewendet haben:

Hinweis

Msg 5289, Ebene 16, Status 1, Zeile 1
Der gruppierte Columnstore-Index "cci" für die Tabelle "t" verfügt über einen oder mehrere Datenwerte, die nicht mit Datenwerten in einem Wörterbuch übereinstimmen. Stellen Sie die Daten aus einer Sicherung wieder her.

Wenn Sie in einer aktuell betroffenen Datenbank eine Abfrage ausführen, die die betroffenen Tabellen überprüft, nachdem Sie diesen Fix angewendet haben, erhalten Sie die folgende Fehlermeldung:

Hinweis

Msg 5288, Ebene 16, Status 1, Zeile 1
Der Columnstore-Index verfügt über einen oder mehrere Datenwerte, die nicht mit Datenwerten in einem Wörterbuch übereinstimmen. Führen Sie DBCC CHECKDB aus, um weitere Informationen zu erhalten.

Wenn Sie diese Fehler erhalten, können Sie die nicht korrigierten Daten speichern, indem Sie die Daten von nicht betroffenen Spalten/Zeilengruppen massenexportieren und die Daten dann erneut laden, nachdem Sie den gruppierten Columnstore-Index gelöscht oder erstellt haben. Sie sollten das Ablaufverfolgungsflag 10207 aktivieren, um den Fehler 5288 zu unterdrücken, und rückgängig machen auf das alte Verhalten, beschädigte Zeilengruppen zu überspringen.

Hinweis Die Fehlermeldungen 5288 und 5289 werden für diese Zeilengruppe R3 mit segment S3 generiert. Das Ablaufverfolgungsflag 10207 wird verwendet, um die Segmente der Zeilengruppe R3 zu extrahieren, die nicht vom fehlenden Wörterbuch D1 betroffen sind.

Abfrage für betroffene Datenbanken Um festzustellen, ob die Datenbank, die Columnstore-Indizes enthält, bereits von diesem Problem betroffen ist, führen Sie die folgende Abfrage aus:

select  
       object_name(i.object_id) as table_name, 
       i.name as index_name, 
       p.partition_number, 
       count(distinct s.segment_id) as damaged_rowgroups 
from 
       sys.indexes i 
       join sys.partitions p on p.object_id = i.object_id and p.index_id = i.index_id 
       join sys.column_store_row_groups g on g.object_id = i.object_id and g.index_id = i.index_id and g.partition_number = p.partition_number 
       join sys.column_store_segments s on s.partition_id = p.partition_id and s.segment_id = g.row_group_id 
where  
       i.type in (5, 6) 
       and s.secondary_dictionary_id <> -1  
       and g.state_description = 'COMPRESSED' 
       and s.secondary_dictionary_id not in 
       ( 
              select dictionary_id from sys.column_store_dictionaries d 
              where d.hobt_id = p.hobt_id and d.column_id = s.column_id 
       ) 
group by  
       object_name(i.object_id), 
       i.name, 
       p.partition_number 

Notizen

  • Sie müssen diese Abfrage für jede Datenbank ausführen, die Columnstore-Indizes auf dem Server enthält, auf dem SQL Server ausgeführt wird. Ein leeres Resultset gibt an, dass die Datenbank nicht betroffen ist.

  • Führen Sie diese Abfrage in einem Zeitraum aus, in dem keine Aktivität vorhanden ist, die neue Zeilengruppen erstellt oder den Zustand vorhandener Zeilengruppen ändert. Die folgenden Aktivitäten können z. B. den Status von Zeilengruppen ändern: Indexerstellung, Indexreorganisation, Masseneinfügung, Tupel-Mover zum Komprimieren von Deltaspeichern.

    Bevor Sie die Abfrage ausführen, können Sie die Hintergrundtupelverschiebungsaufgabe mithilfe des Ablaufverfolgungsflags 634 deaktivieren. Verwenden Sie diesen Befehl, um die Hintergrundaufgabe zu deaktivieren: DBCC TRACEON ( 634 , -1 ). Denken Sie nach Abschluss der Ausführung der Abfrage daran, die Hintergrundaufgabe mit dem Befehl DBCC TRACEOFF ( 634 , -1 ) erneut zu aktivieren.

    Stellen Sie außerdem sicher, dass keine BULK INSERT/BCP/SELECT-INTO-Befehle vorhanden sind, die Daten in die Tabellen einfügen, die den Columnstore-Index verwenden, während diese Abfrage ausgeführt wird.

    Es wird empfohlen, diese Schritte auszuführen, um zu verhindern, dass die Abfrage falsch positive Ergebnisse zurückgibt.

Status

Microsoft hat bestätigt, dass dies ein Problem bei den Microsoft-Produkten ist, die im Abschnitt „Gilt für“ aufgeführt sind.