Direkt zum Inhalt

Wie behebe ich Fehler bei einer AWS-DMS-Aufgabe, die mit der Fehlermeldung „ERROR: canceling statement due to statement timeout“ fehlschlägt?

Lesedauer: 6 Minute
0

Ich migriere Daten zu oder von meiner On-Premises-PostgreSQL-Datenbank mit AWS Database Migration Service (AWS DMS). Die AWS-DMS-Aufgabe läuft eine Zeit lang normal, dann schlägt die Aufgabe mit einem Fehler fehl. Wie kann ich diese Fehler beheben?

Kurzbeschreibung

Wenn die PostgreSQL-Datenbank die Quelle für deine Migrationsaufgabe ist, ruft AWS DMS während der Volllastphase Daten aus der Tabelle ab. Anschließend liest AWS DMS aus den Write-Ahead-Protokollen (WALs), die während der Change Data Capture (CDC)-Phase vom Replikations-Slot aufbewahrt werden.

Wenn die PostgreSQL-Datenbank das Ziel ist, ruft AWS DMS die Daten von der Quelle ab und erstellt CSV-Dateien in der Replikations-Instance. Anschließend führt AWS DMS einen COPY-Befehl aus, um diese Datensätze während der Volllastphase in das Ziel einzufügen.

Während der CDC-Phase führt AWS DMS jedoch genau die DML-Anweisungen aus den WAL-Quellprotokollen im Transaktions-Anwendungsmodus aus. Im Batch-Anwendungsmodus erstellt AWS DMS während der CDC-Phase zudem CSV-Dateien. Anschließend führt es einen COPY-Befehl aus, um die Nettoveränderungen in das Ziel einzufügen.

Wenn AWS DMS versucht, Daten von der Quelle abzurufen oder im Ziel abzulegen, verwendet es die Standard-Timeout-Einstellung von 60 Sekunden. Wenn die Quelle oder das Ziel stark belastet ist oder Sperren in den Tabellen vorhanden sind, kann AWS DMS die Ausführung dieser Befehle nicht innerhalb von 60 Sekunden beenden. Die Aufgabe schlägt also mit der Fehlermeldung „canceling statement due to statement timeout“ fehl und du siehst einen dieser Einträge im Protokoll:

Nachrichten:

"]E: RetCode: SQL_ERROR SqlState: 57014 NativeError: 1 Message: ERROR: canceling statement due to statement timeout; Error while executing the query [1022502] (ar_odbc_stmt.c:2738)“

„]E: test_decoding_create_replication_slot(...) - Unable to create slot 'lrcyli7hfxcwkair_00016402_8917165c_29f0_4070_97dd_26e78336e01b' (on execute(...) phase) [1022506] (postgres_test_decoding.c:392))“

Gehe wie folgt vor, um diese Fehler zu beheben:

  • Identifiziere die Ursache für lange Laufzeiten von Befehlen.
  • Erhöhe den Timeout-Wert und überprüfe den Timeout-Wert für die Slot-Erstellung.
  • Behebe Probleme bei der Erstellung von Slots.

Lösung

Die Ursache für lange Laufzeiten von Befehlen identifizieren

Um den Befehl zu finden, der während des Timeouts nicht ausgeführt werden konnte, überprüfe das AWS-DMS-Aufgabenprotokoll und den Abschnitt mit den Tabellenstatistiken der Aufgabe. Du findest diese Informationen auch in der PostgreSQL-Fehlerprotokolldatei, wenn der Parameter log_min_error_statement auf ERROR oder einen niedrigeren Schweregrad gesetzt ist. Nachdem du den fehlgeschlagenen Befehl identifiziert hast, kannst du die fehlgeschlagenen Tabellennamen finden. Sieh dir diese Beispielfehlermeldung aus dem PostgreSQL-Fehlerprotokoll an:

ERROR: canceling statement due to statement timeout
STATEMENT: <The statement executed>"

Um Sperren in den zugehörigen Tabellen zu finden, führe diesen Befehl in der Quelle oder im Ziel aus (je nachdem, wo der Fehler auftritt):

SELECT blocked_locks.pid AS blocked_pid,
 blocked_activity.usename AS blocked_user,
 blocking_locks.pid AS blocking_pid,
         blocking_activity.usename AS blocking_user,
         blocked_activity.query    AS blocked_statement,
         blocking_activity.query   AS current_statement_in_blocking_process
   FROM  pg_catalog.pg_locks         blocked_locks
    JOIN pg_catalog.pg_stat_activity blocked_activity  ON blocked_activity.pid = blocked_locks.pid
    JOIN pg_catalog.pg_locks         blocking_locks
        ON blocking_locks.locktype = blocked_locks.locktype
        AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
        AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
        AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
        AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
        AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
        AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
        AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
        AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
        AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
        AND blocking_locks.pid != blocked_locks.pid
    JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
   WHERE NOT blocked_locks.GRANTED;

Wenn du blockierte PIDs findest, halte die blockierte PID an oder beende sie, indem du diesen Befehl ausführst:

SELECT pg_terminate_backend(blocking_pid);

Da tote Zeilen oder „Tupel“ die SELECT-Zeit erhöhen können, suche in den Quelltabellen nach einer großen Anzahl toter Zeilen, indem du diesen Befehl ausführst:

select * from pg_stat_user_tables where relname= 'table_name';

Prüfe, ob die fehlgeschlagene Zieltabelle Primärschlüssel oder eindeutige Indizes enthält. Wenn die Tabelle keine Primärschlüssel oder eindeutigen Indizes enthält, wird während der Ausführung einer UPDATE-Anweisung ein vollständiger Tabellenscan durchgeführt. Dieser Tabellenscan kann sehr lange dauern.

Den Timeout-Wert erhöhen

AWS DMS verwendet das zusätzliche Verbindungsattribut executeTimeout sowohl auf dem Quell- als auch auf dem Zielendpunkt. Der Standardwert für executeTimeout ist 60 Sekunden, sodass AWS DMS ein Timeout durchführt, wenn die Ausführung einer Abfrage länger als 60 Sekunden dauert.

Wenn der Fehler bei Source_Unload oder Source_Capture auftritt, lege den Timeout-Wert für executeTimeout in der Quelle fest. Wenn der Fehler bei Target_Load oder Target_Apply auftritt, lege den Timeout-Wert für executeTimeout im Ziel fest. Erhöhe die Einstellung für den Timeout-Wert, indem du die folgenden Schritte ausführst:

1.    Öffne die AWS-DMS-Konsole.

2.    Wähle im Navigationsbereich Endpunkte aus.

3.    Wähle den PostgreSQL-Endpunkt aus.

4.    Wähle Aktionen und anschließend Ändern aus.

5.    Erweitere den Abschnitt Endpunktspezifische Einstellungen.

6.    Gib in das Feld für Extra Verbindungsattribute den folgenden Wert ein:

executeTimeout=3600;

7.    Wähle Speichern aus.

8.    Wähle im Bereich Endpunkte den Namen des PostgreSQL-Endpunkts aus.

9.    Im Abschnitt Verbindungen ändert sich der Status des Endpunkts von Wird getestet zu Successful (Erfolgreich).

Du kannst den Parameter statement_timeout in der PostgreSQL-DB-Instance erhöhen (in Millisekunden). Der Standardwert ist 0, wodurch Timeouts für sämtliche Abfragen deaktiviert werden. Du kannst ebenfalls den Parameter lock_timeout erhöhen. Der Standardwert ist 0, wodurch Timeouts für Sperren deaktiviert werden.

Probleme bei der Slot-Erstellung beheben

Wenn das Timeout aufgetreten ist, als du den Replikationsslot in der PostgreSQL-Datenbank erstellt hast, werden Protokolleinträge angezeigt, die den folgenden ähneln:

Nachrichten

„]E: test_decoding_create_replication_slot(...) - Unable to create slot 'lrcyli7hfxcwkair_00016402_8917165c_29f0_4070_97dd_26e78336e01b' (on execute(...) phase) [1022506] (postgres_test_decoding.c:392)“

Du kannst dieses Timeout erhöhen, indem du den Parameter TransactionConsistencyTimeout im Abschnitt Aufgabeneinstellungen konfigurierst. Der Standardwert ist 600 Sekunden.

PostgreSQL kann den Replikationsslot nicht erstellen, wenn die Datenbank-Benutzertabellen aktive Sperren enthalten. Überprüfe, ob Sperren vorhanden sind, indem du diesen Befehl ausführst:

select * from pg_locks;

Führe anschließend, um zu testen, ob der Fehler behoben wurde, diesen Befehl aus, um den Replikationsslot in der PostgreSQL-Quelldatenbank manuell zu erstellen:

select  xlog_position FROM pg_create_logical_replication_slot('<Slot name as per
    the task log>', 'test_decoding');

Wenn der Befehl den Slot immer noch nicht erstellen kann, musst du möglicherweise mit einem PostgreSQL-DBA arbeiten, um den Engpass zu identifizieren und die Datenbank zu konfigurieren. Wenn der Befehl erfolgreich ist, lösche den Slot, den du gerade zu Testzwecken erstellt hast:

select pg_drop_replication_slot(‘<slot name>');

Starte abschließend die Migrationsaufgabe neu.


Ähnliche Informationen

PostgreSQL-Dokumentation zu Standardeinstellungen für Client-Verbindungen

Zusätzliche Verbindungsattribute bei Verwendung von PostgreSQL als Ziel für AWS DMS

Zusätzliche Verbindungsattribute bei Verwendung von PostgreSQL als DMS-Quelle

Verwendung einer PostgreSQL-Datenbank als AWS-DMS-Quelle