Wie kann ich eine AWS-DMS-Aufgabe beheben, 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 Ihre 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 Sie sehen 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))“

Gehen Sie wie folgt vor, um diese Fehler zu beheben:

  • Identifizieren Sie die Ursache für lange Laufzeiten von Befehlen.
  • Erhöhen Sie den Timeout-Wert und überprüfen Sie den Timeout-Wert für die Slot-Erstellung.
  • Beheben Sie 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üfen Sie das AWS-DMS-Aufgabenprotokoll und den Abschnitt mit den Tabellenstatistiken der Aufgabe. Sie finden diese Informationen auch in der PostgreSQL-Fehlerprotokolldatei, wenn der Parameter log_min_error_statement auf ERROR oder einen niedrigeren Schweregrad gesetzt ist. Nachdem Sie den fehlgeschlagenen Befehl identifiziert haben, können Sie die fehlgeschlagenen Tabellennamen finden. Sehen Sie sich 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ühren Sie 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 Sie blockierte PIDs finden, halten Sie die blockierte PID an oder beenden Sie sie, indem Sie diesen Befehl ausführen:

SELECT pg_terminate_backend(blocking_pid);

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

select * from pg_stat_user_tables where relname= 'table_name';

Prüfen Sie, 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, legen Sie den Timeout-Wert für executeTimeout in der Quelle fest. Wenn der Fehler bei Target_Load oder Target_Apply auftritt, legen Sie den Timeout-Wert für executeTimeout im Ziel fest. Erhöhen Sie die Einstellung für den Timeout-Wert, indem Sie die folgenden Schritte ausführen:

1.Öffnen Sie die AWS-DMS-Konsole.

2.Wählen Sie im Navigationsbereich Endpunkte aus.

3.Wählen Sie den PostgreSQL-Endpunkt aus.

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

5.Erweitern Sie den Abschnitt Endpunktspezifische Einstellungen.

6.Geben Sie in das Feld für Zusätzliche Verbindungsattribute den folgenden Wert ein:

executeTimeout=3600;

7.Wählen Sie Speichern aus.

8.Wählen Sie im Bereich Endpunkte den Namen Ihres PostgreSQL-Endpunkts aus.

9.Im Abschnitt Verbindungen ändert sich der Status des Endpunkts von Testing zu Successful.

Sie können 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. Sie können 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 Sie den Replikationsslot in der PostgreSQL-Datenbank erstellt haben, 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)“

Sie können dieses Timeout erhöhen, indem Sie den Parameter TransactionConsistencyTimeout im Abschnitt Aufgabeneinstellungen konfigurieren. Der Standardwert ist 600 Sekunden.

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

select * from pg_locks;

Führen Sie 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, müssen Sie möglicherweise mit einem PostgreSQL-DBA arbeiten, um den Engpass zu identifizieren und Ihre Datenbank zu konfigurieren. Wenn der Befehl erfolgreich ist, löschen Sie den Slot, den Sie gerade zu Testzwecken erstellt haben:

select pg_drop_replication_slot(‘<slot name>');

Starten Sie abschließend Ihre 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