¿Cómo soluciono que una tarea de AWS DMS falle y aparezca el mensaje de error «ERROR: cancelación de la sentencia debido al tiempo de espera de la sentencia»?

7 minutos de lectura
0

Estoy migrando datos hacia o desde mi base de datos local de PostgreSQL con AWS Database Migration Service (AWS DMS). La tarea de AWS DMS se ejecuta de forma normal durante un tiempo y después se produce un error. ¿Cómo puedo solucionar estos errores?

Descripción breve

Si la base de datos de PostgreSQL es el origen de la tarea de migración, AWS DMS obtiene los datos de la tabla durante la fase de carga completa. A continuación, AWS DMS lee los registros de escritura previa (WAL) que se guardan en la ranura de replicación durante la fase de captura de datos modificados (CDC).

Si el destino es la base de datos de PostgreSQL, AWS DMS obtiene los datos del origen y crea archivos CSV en la instancia de replicación. A continuación, AWS DMS ejecuta un comando COPY para insertar esos registros en el destino durante la fase de carga completa.

Sin embargo, durante la fase de CDC, AWS DMS ejecuta las sentencias DML exactas de los registros WAL de origen en el modo de aplicación transaccional. Para el modo de aplicación por lotes, AWS DMS también crea archivos CSV durante la fase de CDC. A continuación, ejecuta un comando COPY para insertar los cambios netos en el destino.

Cuando AWS DMS intenta obtener datos del origen o colocarlos en el destino, utiliza la configuración de tiempo de espera predeterminada de 60 segundos. Si el origen o el destino están muy cargados o hay bloqueos en las tablas, AWS DMS no podrá terminar de ejecutar esos comandos en 60 segundos. Por lo tanto, la tarea falla y aparece un error que dice «cancelación de la sentencia debido al tiempo de espera de la sentencia» y aparece una de estas entradas en el registro:

Mensajes:

«]E: RetCode: SQL_ERROR SqlState: 57014 NativeError: 1 mensaje: ERROR: cancelación de la sentencia debido al tiempo de espera de la sentencia; error al ejecutar la consulta [1022502] (ar_odbc_stmt.c:2738)»

«]E: test_decoding_create_replication_slot(...) - No se pudo crear la ranura 'lrcyli7hfxcwkair_00016402_8917165c_29f0_4070_97dd_26e78336e01b' (on execute(...) phase) [1022506] (postgres_test_decoding.c:392))»

Para solucionar estos errores, siga estos pasos:

  • Identifique la causa de la duración prolongada de los tiempos de ejecución de los comandos.
  • Aumente el valor del tiempo de espera y compruebe el valor del tiempo de espera de creación de ranuras.
  • Solucione los problemas con la creación de ranuras.

Resolución

Identificar la causa de la duración prolongada de los tiempos de ejecución de los comandos

Para encontrar el comando que no se pudo ejecutar durante el período de tiempo de espera, revise el registro de tareas de AWS DMS y la sección de estadísticas de la tabla de la tarea. También puede encontrar esta información en el archivo de registro de errores de PostgreSQL si el parámetro log_min_error_statement está establecido en ERROR o con una gravedad inferior. Tras identificar el comando que falló, podrá buscar los nombres de las tablas con errores. Consulte este ejemplo de mensaje de error del registro de errores de PostgreSQL:

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

Para buscar bloqueos en las tablas asociadas, ejecute este comando en el origen o el destino (según dónde aparezca el error):

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;

Si encuentra algún PID bloqueado, detenga o finalice el PID bloqueado ejecutando este comando:

SELECT pg_terminate_backend(blocking_pid);

Dado que las filas muertas pueden aumentar el tiempo de SELECT, compruebe si hay un gran número de filas muertas en las tablas de origen ejecutando este comando:

select * from pg_stat_user_tables where relname= 'table_name';

Compruebe si la tabla de destino que falla tiene claves principales o índices únicos. Si la tabla no tiene claves principales ni índices únicos, se lleva a cabo un análisis completo de la tabla durante la ejecución de cualquier sentencia UPDATE. Este escaneo de la tabla puede tardar mucho tiempo.

Aumentar el valor del tiempo de espera

AWS DMS usa el atributo de conexión adicional executeTimeout tanto en los puntos de conexión de origen como en los de destino. El valor predeterminado de executeTimeout es de 60 segundos, por lo que AWS DMS agota el tiempo de espera si una consulta tarda más de 60 segundos en ejecutarse.

Si el error aparece en Source_Unload o Source_Capture, defina el valor de tiempo de espera de executeTimeout en el origen. Si el error aparece en Target_Load o Target_Apply, defina el valor de tiempo de espera de executeTimeout en el destino. Para aumentar el valor del tiempo de espera, siga estos pasos:

1.Abra la consola de AWS DMS.

2.Seleccione Puntos de enlace en el panel de navegación.

3.Elija el punto de conexión de PostgreSQL.

4.Elija Acciones y, a continuación, seleccione Modificar.

5.Expanda la sección Configuración específica de punto de conexión.

6.En el campo Atributos de conexión adicionales, introduzca este valor:

executeTimeout=3600;

7.Seleccione Guardar.

8.En el panel Puntos de enlace, elija el nombre del punto de conexión de PostgreSQL.

9.En la sección Conexiones, el Estado del punto de conexión cambia de Pruebas a Correcto.

Puede aumentar (en milisegundos) el parámetro statement_timeout en la instancia de base de datos de PostgreSQL. El valor predeterminado es 0, lo que desactiva los tiempos de espera de cualquier consulta. También puede aumentar el parámetro lock_timeout. El valor predeterminado es 0, lo que desactiva los tiempos de espera de los bloqueos.

Solucionar problemas con la creación de ranuras

Si el tiempo de espera se agotó al crear la ranura de replicación en la base de datos de PostgreSQL, verá entradas de registro similares a las siguientes:

Mensajes

«]E: test_decoding_create_replication_slot(...) - No se pudo crear la ranura 'lrcyli7hfxcwkair_00016402_8917165c_29f0_4070_97dd_26e78336e01b' (on execute(...) phase) [1022506] (postgres_test_decoding.c:392)»

Puede aumentar este tiempo de espera configurando el parámetro TransactionConsistencyTimeout en la sección Configuración de la tarea. El valor predeterminado es 600 segundos.

PostgreSQL no puede crear la ranura de replicación si hay bloqueos activos en las tablas de usuarios de la base de datos. Compruebe si hay bloqueos ejecutando este comando:

select * from pg_locks;

A continuación, para comprobar si el error se ha resuelto, ejecute este comando para crear manualmente la ranura de replicación en la base de datos PostgreSQL de origen:

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

Si el comando sigue sin poder crear la ranura, es posible que tenga que trabajar con un administrador de bases de dato de PostgreSQL para identificar el obstáculo y configurar la base de datos. Si el comando se ejecuta correctamente, elimine la ranura que acaba de crear como prueba:

select pg_drop_replication_slot(‘<slot name>');

Por último, reinicie la tarea de migración.


Información relacionada

Documentación de PostgreSQL para los valores predeterminados de conexión de clientes

Atributos de conexión adicionales cuando se utiliza PostgreSQL como destino para AWS DMS

Atributos de conexión adicionales cuando se usa PostgreSQL como origen de DMS

Uso de una base de datos de PostgreSQL como origen de AWS DMS

OFICIAL DE AWS
OFICIAL DE AWSActualizada hace un año