Ein Access Failure ist der harmloseste der drei Metadatenfehler: Der Treiber kann den Wert nicht lesen, er wirft eine Exception, und der Fehler ist sofort sichtbar. Der Übersichtsartikel Metadaten-Inkonsistenzen in InterSystems IRIS erkennen und beheben behandelt diesen Fall und die beiden folgenden im Überblick.
In diesem Artikel geht es um die anderen beiden. Keiner von beiden erzeugt eine Fehlermeldung, keiner eine Warnung, einen Log-Eintrag oder einen sichtbaren Hinweis. Eine Zeile lässt sich von jedem Client fehlerfrei lesen und widerspricht trotzdem den Metadaten, die derselbe Client zuvor übermittelt bekommen hat. Ich nenne die beiden Varianten Silent Corruption und Undetected Mutation.
Beide stecken in der Datenbank DATATYPE_SAMPLE, Sie können also jeden Schritt selbst nachvollziehen:
Silent Corruption
Die Tabelle Employee enthält einen gezielt manipulierten Datensatz, der das Verhalten zeigt: die Zeile mit ID = 110. Weder auf den ersten noch auf den zweiten Blick ist an ihr etwas auffällig. Weder der Datenbanktreiber noch das Abfragewerkzeug meldet beim Lesen dieser Zeile ein Problem.

Erst bei genauem Hinsehen wird klar, dass der Wert in der markierten Zelle nicht zu den Metadaten passt, die der Treiber für diese Spalte übermittelt hat. Die Spalte Name ist als VARCHAR(50) definiert. Der Wert ist 60 Zeichen lang.

Der Demowert ist so aufgebaut, dass er sich ohne Hilfsmittel prüfen lässt: Er zählt sich in Zehnerblöcken selbst ab und läuft über die Marke 50 hinaus bis 60XxXxXxXx. In einer echten Datenbank wäre der Überhang von einem gewöhnlichen Namen nicht zu unterscheiden.
Warum das ein Problem ist
Es gibt Fälle, in denen dieses Verhalten überhaupt keinen Schaden anrichtet, weil der Treiber die Inkonsistenz nachsichtig behandelt und der Wert ohnehin nur angezeigt wird. Probleme entstehen dort, wo ein nachgelagertes System sich auf die gelieferten Metadaten verlässt. Baut die Weiterverarbeitung auf diesen Definitionen auf, treten Fehler auf, sobald der tatsächliche Inhalt die vereinbarte Schnittstelle verletzt.
ETL-Werkzeuge sind das typische Beispiel. Sie erzeugen Zieltabellen aus den Quell-Metadaten oder leiten Transformationen daraus ab, und ein 60 Zeichen langer Wert, der in einer aus VARCHAR(50) dimensionierten Spalte ankommt, wird abgewiesen oder abgeschnitten. Der Fehler zeigt sich im Zielsystem, weit entfernt von der Zeile, die ihn verursacht hat.
So finden Sie ihn
Die folgende Abfrage ermittelt Datensätze, deren Inhalt von den definierten Metadaten abweicht:
SELECT
Name,
CASE WHEN LENGTH(Name) > 50 THEN 1 ELSE 0 END AS Name_LENGTH_CHECK
,SSN,
CASE WHEN LENGTH(SSN) > 50 THEN 1 ELSE 0 END AS SSN_LENGTH_CHECK
FROM SQLUser.Employee
WHERE
LENGTH(Name) > 50
OR LENGTH(SSN) > 50
Sie liefert ausschließlich die fehlerhaften Zeilen. In jeder Zeile ist die betroffene Zelle mit einer 1 gekennzeichnet, wenn der Wert die in den Metadaten definierte Länge überschreitet.

Undetected Mutation
Der zweite Fehler ist subtiler. DATATYPE_SAMPLE enthält einen Datensatz, der eigens dafür verändert wurde: die Zeile mit ID = 120. Auch hier meldet weder der Treiber noch das Abfragewerkzeug beim Lesen ein Problem.

Diesmal scheint der Wert sogar zu den Metadaten zu passen. Die Spalte Age ist als INTEGER definiert, und die Zelle liefert eine ganze Zahl, in diesem Beispiel 0.
Dieser Wert steht so nicht in der Datenbank. Ein direkter Blick auf das zugrunde liegende Global zeigt den tatsächlichen Inhalt: Durch Manipulation wurde eine Zeichenkette in das Feld geschrieben.

Der Global Browser zerlegt den Knoten ^poCN.D1Ex.1(20) in seine $LISTBUILD-Positionen. Position 2, die als Age projiziert wird, enthält die Zeichenkette "NoINT". Der Treiber kann daraus keine ganze Zahl machen und liefert stattdessen 0. Das Ergebnis ist in sich stimmig und vollständig falsch.
Das ist der Fehlermodus, auf den es im Reporting und bei Migrationen ankommt. Ein Access Failure stoppt den Lauf. Eine Undetected Mutation lässt ihn zu Ende laufen und eine falsche Zahl darin stehen, und eine erzwungene 0 in einer Alters-, Gehalts- oder Mengenspalte wird ohne Fehlermeldung summiert, gemittelt und in Diagramme übernommen.
So finden Sie sie
SELECT
CAST(Age AS VARCHAR(255)) AS Age,
ISNUMERIC(CAST(Age AS VARCHAR(255))) AS Age_ISNUMERIC
FROM SQLUser.Employee
WHERE
ISNUMERIC(CAST(Age AS VARCHAR(255))) = 0
Entscheidend ist die vorgezogene Umwandlung nach VARCHAR: Sie umgeht genau die Typkonvertierung, die vorher die 0 erzeugt hat, und liefert die gespeicherte Repräsentation. Die Abfrage gibt nur die Zeilen mit Metadaten-Inkonsistenz zurück und kennzeichnet die problematische Zelle mit einer 0, wenn der Treiber den Wert nicht als numerisch interpretieren kann.

Die Spalte Age zeigt nun NoINT — den Wert, der wirklich gespeichert war — und Age_ISNUMERIC markiert ihn mit 0.
Fazit
Beide Szenarien zeigen, wie scheinbar wohlgeformte Daten feine Inkonsistenzen verbergen können, besonders in Altsystemen, die an den üblichen Schutzmechanismen vorbeischreiben. Ein Access Failure fällt sofort auf. Silent Corruption und Undetected Mutation bleiben meist unbemerkt und verursachen nachgelagert ernsthafte Probleme, vor allem in Systemen, die auf strikte Metadatentreue angewiesen sind.
Mit der Datenbank DATATYPE_SAMPLE und den beiden Abfragen oben lassen sich solche Fälle von Hand aufspüren. Diese Prüfungen von Hand zu schreiben ist allerdings mühsam und fehleranfällig: Jede Spalte braucht ihr eigenes Prädikat, und die Prädikate müssen bei jeder Änderung der Klassendefinition nachgezogen werden.
SQL DATA LENS erzeugt sie stattdessen. Seit Version 3.22 bietet das SQL-Scripting-Menü SELECT with length check und SELECT with numeric check an; beide bauen die obigen Statements aus den aktuellen Metadaten einer Tabelle, einer View oder einer Stored Procedure. Der SQL-Editor führt sie aus, im Table Viewer rufen Sie sie auf, und der Data Inspector zeigt bei einem Befund, wie ein strukturierter Wert tatsächlich kodiert ist.
Wenn Sie das Werkzeug noch nicht installiert haben, beginnen Sie auf der Download-Seite. Zum dritten Fehlermodus, dem, der tatsächlich eine Exception wirft, siehe Metadaten-Inkonsistenzen in InterSystems IRIS erkennen und beheben.
Dieser Artikel erschien zuerst in der InterSystems Developer Community als Testing Metadata Inconsistencies in InterSystems IRIS Using the DATATYPE_SAMPLE Database (Part II) — Silent Corruption. SQL DATA LENS ist außerdem auf InterSystems Open Exchange gelistet.