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.