SQL 2016 SQL Server-Zusicherung: Datei: <pageref.cpp>, Zeile = 951 Fehlgeschlagene Zusicherung

8

Ich aktualisiere derzeit unser Data Warehouse von SQL 2012 auf SQL 2016. Ich habe sowohl meine alten als auch meine neuen DWs parallel nebeneinander ausgeführt.

Mein ETL-Prozess (ein von einem Drittanbieter in SSIS entwickeltes Framework) wurde 2012 mehr als zwei Jahre lang erfolgreich ausgeführt, schlägt jedoch 2016 fehl. Bisher sind die Datenbanken und der ETL-Prozess identisch.

Beide Server sind virtuelle Maschinen, die unter VMWare ausgeführt werden. Alter Server ist Win 2008 mit 24 GB RAM. SQL 2012 Std. Maximales Mem auf 16 GB eingestellt. Neuer Server ist Win 2012 mit 64 GB RAM. SQL 2016 dev. Maximales Mem auf 50 GB eingestellt. In New DW wird v13.0.1601.5 RTM Developer Edition (64-Bit) ausgeführt.

Während der Ausführung meines ETL-Prozesses schlagen die Ladeschritte, die eine SQL-Zusammenführung in eine Dimension oder eine Faktentabelle verwenden, mit dem folgenden Fehler fehl.

Voller Text:

BESCHREIBUNG: SQL Server-Zusicherung: Datei :, Zeile = 951 Fehlgeschlagene Zusicherung = 'IS_OFF (BUF_MINLOGGED, m_buf-> bstat) || pageModifyType! = PageModifyType_Contents || GetPagePtr () -> IsTextPage () '. Dieser Fehler kann zeitabhängig sein. Wenn der Fehler nach dem erneuten Ausführen der Anweisung weiterhin besteht, überprüfen Sie die Datenbank mit DBCC CHECKDB auf strukturelle Integrität oder starten Sie den Server neu, um sicherzustellen, dass die speicherinternen Datenstrukturen nicht beschädigt werden.

Wie empfohlen habe ich DBCC ausgeführt und es wurden keine Fehler gefunden. Ich habe auch SQL neu gestartet. Ich habe dann den ETL-Prozess neu gestartet und den gleichen Fehler erhalten.

Meine Suche nach diesem Fehler zeigt, dass ein bekannter Fehler in SQL 2008, 2012 und 2014 bekannt war und in nachfolgenden Hotfixes und kumulativen Updates behoben wurde. Ich bin ein bisschen überrascht, dass es 2016 wieder auftaucht.

Die gefundenen Links wirken sich auf SSIS aus, wenn versucht wird, Einfügungen vorzunehmen, wenn sich die Datenbank im Wiederherstellungsmodell "Einfach" oder "Massenprotokolliert" befindet. (Ich verwende ein einfaches Wiederherstellungsmodell.)

Eine empfohlene Problemumgehung besteht darin, das Db-Wiederherstellungsmodell in FULL zu ändern. Ich habe es versucht und es funktioniert, aber es ist keine gute Lösung für ein Data Warehouse.

Hat das noch jemand mit 2016 erlebt?

Kann jemand alternative Problemumgehungen vorschlagen?

Aktualisierung:

26.7.2016: Ich habe das Critical Update KB3164398 (v13.0.1708.0) angewendet und das Problem besteht weiterhin.

27/7/2016: Ich habe das kumulative Update CU1 KB3164674 (v13.0.2149.0) angewendet.

08.03.2016: Bei unserem kleinsten Würfel ist über Nacht ein Fehler aufgetreten. CU1 hat das Problem nicht behoben. Heute habe ich den Fehler bei MS Connect gemeldet und einen Supportanruf bei Microsoft protokolliert.

08.12.2016: Der MS-Support antwortete zunächst, aber die Antwort lautete "Wir haben keine Lösung dafür". Der Support-Mitarbeiter wollte es mit seinen Kollegen besprechen und sich bei mir melden. 8 Tage später habe ich nichts von ihm gehört.

Obwohl ich keine Lösung gefunden habe, haben wir eine Problemumgehung gefunden, die zu uns passt. Siehe meine gepostete Antwort.

29.9.2016. Ich habe letzte Woche CU2 angewendet. Am Donnerstag haben wir versehentlich eine alte Version der Zusammenführung ausgeführt, die mit demselben Fehler erneut fehlgeschlagen ist. Also .. CU2 hat es auch nicht behoben.

23/1/2017 : Ich habe 2016 SP1 CU1 angewendet und glaube, dass dies das Problem behoben hat. Insbesondere KB3205964

Sir schwört viel
quelle

Antworten:

2

Wenn Sie sich die KB ansehen, haben Sie einige Optionen / Problemumgehungen:

  1. Wechseln Sie zum vollständigen Wiederherstellungsmodell. Sie sagen, "dies ist keine große Option für ein Lager", aber es geht wirklich nur darum, die Transaktionsprotokollsicherungen regelmäßig einzurichten, z. B. 15 Minuten, und sie dann zu entsorgen. SSIS / Wartungspläne haben dafür Lageraufgaben . Sie werden massenprotokollierte Transaktionen verlieren, aber ich habe nie festgestellt, dass diese einen großen Unterschied in der Laufzeit bewirken, nur die Protokollgröße. Sie können sogar ein Protokoll auf nul sichern, was ich hier nicht beschreiben werde. Wenn Sie sich nicht sicher sind, was Sie tun sollen, fragen Sie Ihren lokalen DBA. Speicherplatz und Aufbewahrung von Transaktionsprotokollsicherungen sind leichter zu lösen als schwerwiegende Fehler. Wenn dieses Problem irgendwann behoben ist, können Sie zurückschalten.
  2. Die KB erwähnt "mehrere BULK INSERT-Anweisungen in einer einfach verteilten Transaktion". Aus Ihrer Frage geht nicht hervor, wie Ihre Masseneinsätze eingerichtet sind. Verwenden Sie SSIS, um 'Execute SQL'-Aufgaben auszuführen, die das verwendenMERGEBefehl? Was bedeutet hier "mehrere BULK INSERTs"? Gibt es eine Möglichkeit, Ihren Ansatz beispielsweise einzeln in einzelne BULK INSERTs umzuwandeln? In SSIS können Sie die 'MaxConcurrentExecutables' vorübergehend auf 1 setzen, um zu sehen, ob dies hilfreich ist. Binden Sie es an eine Konfigurationsvariable, damit Sie es später wieder ändern können. Natürlich wird es die Dinge verlangsamen, aber Sie ziehen es vor, dass Ihre ETL beendet wird, anstatt schnell zu scheitern. Paralleles Arbeiten ist ein gutes Muster und eine echte Stärke von SSIS, aber Sie können nur so schnell fahren wie Ihre langsamste Komponente. Angenommen, Sie haben 10 Dimensionen, die eine Minute dauern, und eine Tatsache, die eine Stunde dauert. Ihre ETL endet in einer Stunde, die parallel oder 1 Stunde und 10 Minuten in Serie läuft.
  3. MERGEist nett, hat aber ein paar Probleme. Sie könnten in Betracht ziehen, wieder nach INSERT/ zu konvertieren UPDATE. Auch sollten Sie HOLDLOCKmit MERGEgemäß hier verwenden . Verwenden Sie diesen Hinweis? Macht es für dieses Problem einen Unterschied, wenn Sie dies tun? Wir hatten ein Problem in einem frühen SQL 2014-Build, bei dem die Verwendung MERGEmit zusammensetzbarer DML ( OUTPUTKlausel) in den Spaltenspeicher diese Art von Behauptung verursachte. Ich ließ sie die Spaltenspeicherindizes aus den Dimensionen entfernen, die sie hinzugefügt hatten, ohne es mir mitzuteilen.
  4. Welche Art von Transaktionsabwicklung machen Sie? Manchmal kann die Position mit ETL durch einfaches erneutes Ausführen wiederholt werden. Manchmal muss es fehlschlagen und zurückgesetzt werden. Wie haben Sie das umgesetzt? Kann geändert werden, damit es sich nicht um eine "einzelne verteilte Transaktion" handelt?

Viel Glück.

wBob
quelle
Hallo @wBob, danke für deine Antwort. Um Ihre Fragen zu beantworten. 1. Wir sprechen über das Extrahieren von 20-30 GB-Tabellen in einem einzigen Schritt. Verschieben von über 100 GB Daten. Ich mache mir Sorgen um das Ausblasen der TX-Protokolle und auch des Speichers. Vielleicht könnte ich die Protokollsicherung nach jedem Extrakt zu einem Schritt in der ETL machen? 2. Ja, SSIS ruft eine SQL-Task auf, um eine Zusammenführung durchzuführen. Jeder Schritt wird nacheinander ausgeführt. Zum Zeitpunkt der Ausführung der Zusammenführung ist dies die einzige auszuführende Aufgabe. 3. Unser ETL-Tool ist ein Framework, das von einem Anbieter bereitgestellt wird. So funktioniert es. Ich bin mir nicht sicher über Hinweise. wird überprüfen. 4. Keine TX-Behandlung. Straight SQL.
Sir Swears-a-lot
Wenn die erfolgreichen Läufe nicht fortgesetzt werden, versuchen Sie nach jeder Tabellenverschiebung ein 100-GB-T-Protokoll mit Protokollsicherungen, das es sortieren sollte. Natürlich muss man testen. Gibt es noch andere Funktionen, die wir über das Ziel wissen sollten? Columnstore, Partitionierung, übermäßige Indizierung?
wBob
Derzeit gibt es keine Funktionen, die noch nicht in unserer bestehenden DW für 2012 Standard enthalten sind. Die neuen DW / Datamarts sind exakte Kopien von Originalen, keine Spaltenspeicher oder Partitionierung. Minimale (aber effektive) Indizes. Wir konzentrieren uns derzeit auf einen Plattformwechsel wie für wie. Letztendlich wird unser neues Produkt DW 2016 Enterprise sein. Wir fügen jedoch erst Funktionen auf Unternehmensebene hinzu, wenn die Grundlagen funktionieren.
Sir Swears-a-lot
Hi @ wBob. Wir haben Ihren Vorschlag sozusagen umgesetzt, indem wir die Einfügung aus der Zusammenführung herausgebrochen haben. Aber angesichts der Art und Weise, wie ich die Frage gestellt habe, bin ich mir nicht sicher, was als richtige Antwort zu qualifizieren ist. Aber ich denke, Sie haben mich zu einer gültigen und praktikablen Problemumgehung geführt.
Sir Swears-a-lot
2

Ich glaube, dies wurde im Jahr 2016 SP1 CU1 behoben.

Speziell von KB3205964

Sir schwört viel
quelle
1

Dies wird durch Anwenden des kumulativen Updates 1 (CU1) für MSSQL2016 behoben, siehe Link https://support.microsoft.com/en-us/kb/3164674

Steve Neshausen
quelle
Steve hat mit mir daran gearbeitet. Wir dachten, wir hätten es gelöst, aber keine Zigarre. Also habe ich Kredit entfernt und herabgestimmt.
Sir schwört viel
1

Ich glaube, wir haben eine andere Problemumgehung gefunden. Ich poste meine Antwort, da ich denke, dass sie nützlich sein kann, und sie unterscheidet sich genug von wBobs Vorschlag.

Wir haben den Einfügeteil der Merge-Anweisung so geändert, dass er in eine temporäre Tabelle und nicht in das ursprüngliche Ziel eingefügt wird.

Sobald die Merge-Anweisung ausgeführt wird, fügen wir sie aus der # -Tabelle in das Ziel ein.

Es ist nicht ideal, aber zumindest die Zusammenführung behandelt die Komplexität des "Upsert" immer noch, indem Zeilen markiert werden, die zurückgezogen / abgelaufen sind.

Wir haben festgestellt, dass dies ein akzeptabler Kompromiss ist, verglichen mit dem vollständigen Umschreiben der Zusammenführung als separate Einfügungen und Aktualisierungen.

CREATE TABLE #Activity(
[ETL_ActivitySurrogateKey] [int] IDENTITY(1,1) NOT NULL,
[Field1] [varchar](255) NULL,
)

-- Insert statements for procedure here
INSERT INTO #Activity ( [Field1],2,3,etc )

SELECT [Field1],2,3,etc
FROM 
(
    MERGE [DDS_OZ_CC].[dimActivity] AS target 
    USING (
      SELECT [Field1],2,3,etc
      FROM [STAGE_OZ_CC].[Transform_Activity]
      ) as source
    ON
    (
      target.RowIsCurrent = source.RowIsCurrent
         AND target.[Field1] = source.[Field1]
    )
    WHEN MATCHED 
        AND (        
        EXISTS (SELECT target.Level5Id EXCEPT SELECT source.Level5Id)
    )
    THEN
      UPDATE SET 
        ETL_ValidToDateTime = source.ETL_ValidFromDateTime 
       ,ETL_RowIsCurrent = 0 
       ,ETL_LastTouchedBy = source.ETL_LastTouchedBy 
       ,ETL_RowChangeReason = 'SCD2 Retired' 

    WHEN NOT MATCHED THEN 
    INSERT 
    (    
     [Field1],2,3,etc
    )
    VALUES (      
      source.[Field1],2,3,etc
    )
       WHEN NOT MATCHED BY SOURCE AND target.ETL_RowIsCurrent = 1
       THEN UPDATE SET
       ETL_RowIsCurrent = 0 
       ,ETL_RowChangeReason = 'Fact Removed' 
       ,ETL_LastTouchedBy = 'Unknown'

  OUTPUT
    $action      
      ,source.[Field1],2,3,etc    

  ) AS MergeOutput
  (
    action  
    ,[Field1],2,3,etc   
  ) 

  WHERE ACTION = 'UPDATE' AND ETL_RowIsCurrent = 1

    INSERT INTO [DDS_OZ_CC].[dimActivity]
    ( [Field1],2,3,etc  )
    SELECT [Field1],2,3,etc
    FROM #Activity

    END
Sir schwört viel
quelle
Ok danke Peter. Haben Sie aus Interesse den HOLDLOCK-Hinweis ausprobiert?
wBob
Nein, habe ich nicht. Nachdem ich den Artikel von Aaron Bertrands darüber gelesen hatte, war mein Verständnis, dass es wirklich um Parallelitätsprobleme mit mehreren Benutzern ging. In unserem Fall wird nur der ETL-Prozess ausgeführt.
Sir schwört viel
Ich denke, es hat sich gelohnt, nur zu versuchen, herauszufinden, ob Sie ein anderes Verhalten zeigen, und es ist wahrscheinlich die beste Vorgehensweise. Nur zu sagen, dass Sie jetzt nicht gleichzeitig sind, bedeutet nicht, dass Sie möglicherweise nicht in der Zukunft sind. Wie auch immer, gut gemacht bei der Suche nach einer Lösung und beim nächsten Problem
:)
Ich hätte es gerne getan, aber leider stehen wir unter Zeitbeschränkungen. Sobald wir eine praktikable Lösung gefunden hatten, rief der Chef an, um weiterzumachen.
Sir Swears-a-lot