¿Cómo soluciono el error “canceling statement due to conflict with recovery” (cancelando instrucción debido a un conflicto con la recuperación) al consultar la réplica de lectura de mi instancia de base de datos de RDS para PostgreSQL?

Última actualización: 23/06/2022

He configurado una réplica de lectura para mi instancia de Amazon Relational Database Service (Amazon RDS) para PostgreSQL. Aparece el error “canceling statement due to conflict with recovery” (cancelando instrucción debido a un conflicto con la recuperación) cuando consulto la réplica de lectura.

Descripción corta

Este error puede producirse debido a la falta de visibilidad de la instancia principal sobre la actividad que se está produciendo en la réplica de lectura. El conflicto con la recuperación se produce cuando la información de WAL no se puede aplicar en la réplica de lectura porque los cambios pueden obstruir una actividad que ocurre en la réplica de lectura.

Por ejemplo, supongamos que ejecuta una instrucción DROP en la instancia principal cuando se ejecuta una instrucción SELECT de larga ejecución en la réplica de lectura de la tabla que se pierde en la instancia principal. A continuación, la réplica de lectura tiene dos opciones:

  • Esperar a que termine la instrucción SELECT antes de aplicar el registro WAL. En este caso, el retraso de la replicación aumenta.
  • Aplicar el registro WAL y, a continuación, cancelar la instrucción SELECT. En este caso, aparece el error “canceling statement due to conflict with recovery” (cancelando instrucción debido a un conflicto con la recuperación).

La réplica de lectura resuelve estos conflictos de replicación en función del valor de los parámetros max_standby_streaming_delay y max_standby_archive_delay. El parámetro max_standby_streaming_delay determina cuánto tiempo debe esperar la réplica de lectura antes de cancelar las consultas en espera que entren en conflicto con las entradas de WAL que están a punto de aplicarse. Si la instrucción conflictiva sigue ejecutándose después de este período, PostgreSQL la cancela y emite el siguiente mensaje de error:

ERROR: canceling statement due to conflict with recovery

Este error se produce normalmente debido a consultas de larga duración en la réplica de lectura.

En el ejemplo anterior con la instrucción DROP, la solicitud DROP se almacena en el archivo WAL para aplicarla posteriormente en la réplica de lectura para garantizar la coherencia. Supongamos que ya se está ejecutando una instrucción SELECT en la réplica de lectura que intenta recuperar datos del objeto eliminado con un tiempo de ejecución superior al valor de max_standby_streaming_delay. A continuación, se cancela la instrucción SELECT para que se pueda aplicar la instrucción DROP.

Sesión 1 (Réplica de lectura) Ejecuta una instrucción SELECT en example_table:

postgres=> SELECT * from example_table;

Sesión 2 (Principal) Ejecuta una instrucción DROP en example_table:

postgres=> DROP TABLE example_table;

Aparece el siguiente error:

postgres@postgres:[27544]:ERROR:  canceling statement due to conflict with recovery
postgres@postgres:[27544]:DETAIL:  User was holding a relation lock for too long.
postgres@postgres:[27544]:STATEMENT:  select * from example_table;

Además, puede producirse un conflicto de consultas cuando una transacción en la réplica de lectura lee tuplas que están configuradas para su eliminación en la instancia principal. La eliminación de tuplas seguida de la limpieza en la instancia principal provoca un conflicto con la consulta SELECT que aún se está ejecutando en la réplica. En este caso, la consulta SELECT de la réplica termina con el siguiente mensaje de error:

ERROR:  canceling statement due to conflict with recovery
DETAIL: User query might have needed to see row versions that must be removed.

Resolución

Cuando una réplica de lectura encuentra un conflicto y aparece el error “canceling statement due to conflict with recovery” (cancelando instrucción debido a un conflicto con la recuperación) en el registro de errores, puede establecer ciertos parámetros personalizados en función del mensaje de error para reducir el efecto negativo del conflicto. Tenga en cuenta que los parámetros personalizados se deben configurar en la réplica de lectura.

Aparece el error “canceling statement due to conflict with recovery” (cancelando instrucción debido a un conflicto con la recuperación) con “DETAIL: User was holding a relation lock for too long” (INFORMACIÓN: El usuario ha mantenido un bloqueo de relación durante demasiado tiempo)

max_standby_streaming_delay/max_standby_archive_delay: puede usar estos parámetros para dejar más tiempo antes de cancelar las instrucciones en espera que entren en conflicto con las entradas de WAL a punto de aplicarse. Estos valores representan la cantidad total de tiempo durante la que se permite aplicar los datos de WAL después de recibir los datos de la instancia principal. Estos parámetros se especifican en función del lugar desde el que se leen los datos de WAL. Si los datos WAL se leen desde la replicación de streaming, utilice el parámetro max_standby_streaming_delay. Si los datos de WAL se leen desde la ubicación de archivo en Amazon Simple Storage Service (Amazon S3), utilice el parámetro max_standby_archive_delay.

Tenga en cuenta lo siguiente al configurar estos parámetros:

  • Si establece los valores de estos parámetros en -1, se permite que la instancia de réplica espere indefinidamente a que se completen las consultas conflictivas, lo que aumenta el retraso de la replicación.
  • Si establece los valores de estos parámetros en 0, las consultas conflictivas se cancelan y las entradas WAL se aplican a la instancia de réplica.
  • El valor predeterminado de estos parámetros se establece en 30 segundos.
  • Si no especifica la unidad al configurar estos parámetros, se considera que la unidad es el milisegundo.

Ajuste los valores de estos parámetros para equilibrar la cancelación de consultas o el retraso de replicación en función de su caso de uso.

Nota: Si va a aumentar max_standby_archive_delay para evitar cancelar consultas que entren en conflicto con la lectura de entradas de archivo de WAL, considere aumentar max_standby_streaming_delay también para evitar cancelaciones vinculadas a conflictos con entradas de WAL de streaming.

Aparece el error “canceling statement due to conflict with recovery” (cancelando instrucción debido a un conflicto con la recuperación) con “DETAIL: User query might have needed to see row versions that must be removed (INFORMACIÓN: La consulta del usuario puede haber necesitado ver las versiones de fila que deben eliminarse)

hot_standby_feedback: si activa este parámetro, se envían mensajes de comentarios a la instancia principal desde la réplica de lectura con información de la transacción activa más antigua. Por lo tanto, la instancia principal no elimina los registros que la transacción pueda necesitar.

Al activar este parámetro en la réplica de lectura, las consultas de larga ejecución en la réplica de lectura pueden provocar un aumento de la tabla en la instancia principal. Esto se debe a que las operaciones de vacío no eliminan las tuplas inactivas que podrían necesitar las consultas que se ejecutan en la réplica de lectura. Este parámetro está desactivado de forma predeterminada. Por lo tanto, tenga cuidado al activar este parámetro.

También puede inspeccionar la vista pg_stat_database_conflicts en la réplica de lectura para obtener estadísticas sobre las declaraciones que se cancelan debido a conflictos con la recuperación en la réplica de lectura.


¿Le resultó útil este artículo?


¿Necesita asistencia técnica o con la facturación?