ERROR PostgreSQL: cancelación de la declaración debido a un conflicto con la recuperación

139

Recibo el siguiente error al ejecutar una consulta en una base de datos PostgreSQL en modo de espera. La consulta que causa el error funciona bien durante 1 mes, pero cuando consulta durante más de 1 mes se produce un error.

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

¿Alguna sugerencia de cómo resolverlo? Gracias

Un aprendiz
fuente
Busque el documento de AWS que menciona este error, también tiene la solución aws.amazon.com/blogs/database/…
arunjos007

Respuestas:

89

Ejecutar consultas en el servidor en espera activo es algo complicado: puede fallar, porque durante la consulta algunas filas necesarias pueden actualizarse o eliminarse en primaria. Como un primario no sabe que una consulta se inicia en el secundario, cree que puede limpiar (aspirar) las versiones antiguas de sus filas. Luego, la secundaria tiene que volver a reproducir esta limpieza y tiene que cancelar por la fuerza todas las consultas que puedan usar estas filas.

Las consultas más largas se cancelarán con mayor frecuencia.

Puede solucionar esto iniciando una transacción de lectura repetible en primaria que realiza una consulta ficticia y luego permanece inactiva mientras se ejecuta una consulta real en secundaria. Su presencia evitará la aspiración de versiones antiguas de fila en primaria.

Más información sobre este tema y otras soluciones se explican en la sección Hot Standby - Manejo de conflictos de consultas en la documentación.

Tometzky
fuente
10
Para los usuarios de PostgreSQL 9.1+: consulte la respuesta de eradman a continuación para obtener una solución práctica.
Zoltán
3
Para los usuarios de PostgreSQL 9.1+: la respuesta de max-malysh es mucho más sensata. No haga la sugerencia de Eradman a menos que comprenda los riesgos.
Davos
91

No hay necesidad de tocar hot_standby_feedback. Como otros han mencionado, configurarlo onpuede inflar master. Imagine abrir una transacción en un esclavo y no cerrarla.

En su lugar, establecer max_standby_archive_delayy max_standby_streaming_delayhasta cierto valor cuerdo:

# /etc/postgresql/10/main/postgresql.conf on a slave
max_standby_archive_delay = 900s
max_standby_streaming_delay = 900s

De esta forma, las consultas sobre esclavos con una duración inferior a 900 segundos no se cancelarán. Si su carga de trabajo requiere consultas más largas, simplemente configure estas opciones en un valor más alto.

Max Malysh
fuente
1
Esta es la solución que terminamos usando. Parece el mejor compromiso entre todas las opciones presentadas aquí.
mohit6up
2
Esta es la mejor respuesta. Tenga en cuenta que según los documentos, estos son acumulativos; si tiene varias consultas en la réplica que retiene la réplica, entonces podría ser que llegue a 899 y luego se cancele otra consulta de 2 segundos. Lo mejor es implementar un retroceso exponencial en su código. Además, la demora de transmisión está en vigencia mientras la replicación está transmitiendo. Si la replicación no puede seguir el ritmo de la transmisión, pasará a la replicación desde el archivo. Si está replicando desde un archivo, probablemente debería dejar que se ponga al día, max_standby_archive_delaypodría ser más pequeño que el otro.
Davos
2
Esta sigue siendo la mejor solución aquí. Tenga en cuenta que en Redshift, puede establecer esto a través de la configuración del grupo de parámetros, solo que debería estar en ms, es decir, 900s = 16 minutos = 900000ms.
NullDev
Para actualizar esto en GCP, también en ms cloud.google.com/sql/docs/postgres/…
howMuchCheeseIsTooMuchCheese
Siempre que el propósito del modo de espera sea, por ejemplo, para informar y no sea un modo de espera activo que deba estar listo para manejar la conmutación por error, esta es absolutamente la mejor respuesta.
soupdog
77

No hay necesidad de iniciar transacciones inactivas en el maestro. En postgresql-9.1, la forma más directa de resolver este problema es estableciendo

hot_standby_feedback = on

Esto hará que el maestro esté al tanto de las consultas de larga duración. De los documentos :

La primera opción es establecer el parámetro hot_standby_feedback, que evita que VACUUM elimine las filas muertas recientemente y así no se producen conflictos de limpieza.

¿Por qué no es este el valor predeterminado? Este parámetro se agregó después de la implementación inicial y es la única forma en que un modo de espera puede afectar a un maestro.

eradman
fuente
11
Este parámetro debe establecerse en el modo de espera.
Steve Kehlet
3
Hay algunas desventajas para el maestro en este caso Hot-Standby-Feedback
Evgeny Liskovets
50

Como se indica aquí sobre hot_standby_feedback = on:

Bueno, la desventaja es que el modo de espera puede inflar al maestro, lo que también puede sorprender a algunas personas.

Y aqui :

¿Con qué configuración de max_standby_streaming_delay? Prefiero usar ese valor predeterminado a -1 que el predeterminado hot_standby_feedback. De esa manera, lo que haces en el modo de espera solo afecta al modo de espera


Entonces agregué

max_standby_streaming_delay = -1

Y no más pg_dumperrores para nosotros, ni maestro hinchazón :)

Para la instancia de AWS RDS, consulte http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html

Gilles Quenot
fuente
1
@lennard, esto funcionó para mí. Agregué esta configuración en el postgresql.conf del esclavo, luego reinicié el esclavo.
Ardee Aram
13
Puede obtener un retraso de réplica ilimitado de esta manera, por supuesto. Y si está utilizando una ranura de replicación para conectar la réplica al maestro, eso puede resultar en una retención excesiva de xlog en el maestro, por lo que en realidad solo es viable si está utilizando el archivo WAL.
Craig Ringer
77
¿Cómo configurar esto en AWS RDS?
Kris MP
1
@KrisMP Use psql
Yehonatan
44
@KrisMP en el grupo de parámetros - docs.aws.amazon.com/AmazonRDS/latest/UserGuide/…
r3m0t
13

Los datos de la tabla en el servidor esclavo de reserva activa se modifican mientras se ejecuta una consulta de larga duración. Una solución (PostgreSQL 9.1+) para asegurarse de que los datos de la tabla no se modifiquen es suspender la replicación y reanudar después de la consulta:

select pg_xlog_replay_pause(); -- suspend
select * from foo; -- your query
select pg_xlog_replay_resume(); --resume
David Jaspers
fuente
1
Esto requiere derechos de superusuario. Por lo tanto, podría no ser una solución en algunos casos.
Joao Baltazar
1
En PostgreSQL 10, xlogse reemplazó con wal, por lo que desea llamar pg_wal_replay_pause()y pg_wal_replay_resume().
womble
3

Puede ser demasiado tarde para la respuesta, pero nos enfrentamos al mismo tipo de problema en la producción. Anteriormente solo teníamos un RDS y, a medida que aumentaba el número de usuarios en el lado de la aplicación, decidimos agregar Read Replica para él. La réplica de lectura funciona correctamente en la puesta en escena, pero una vez que pasamos a la producción, comenzamos a obtener el mismo error.

Entonces resolvemos esto habilitando la propiedad hot_standby_feedback en las propiedades de Postgres. Nos referimos al siguiente enlace

https://aws.amazon.com/blogs/database/best-practices-for-amazon-rds-postgresql-replication/

Espero que sea de ayuda.

Tushar.k
fuente
2

Voy a agregar información actualizada y referencias a la excelente respuesta de @ max-malysh arriba.

En resumen, si hace algo en el maestro, debe replicarse en el esclavo. Postgres utiliza registros WAL para esto, que se envían después de cada acción registrada en el maestro al esclavo. El esclavo ejecuta la acción y los dos están nuevamente sincronizados. En uno de varios escenarios, puede estar en conflicto con el esclavo con lo que viene del maestro en una acción WAL. En la mayoría de ellos, está ocurriendo una transacción en el esclavo que entra en conflicto con lo que la acción WAL quiere cambiar. En ese caso, tiene dos opciones:

  1. Retrasar la aplicación de la acción WAL por un momento, permitiendo que el esclavo finalice su transacción conflictiva, luego aplique la acción.
  2. Cancele la consulta conflictiva en el esclavo.

Nos preocupa el # 1 y dos valores:

  • max_standby_archive_delay - este es el retraso utilizado después de una larga desconexión entre el maestro y el esclavo, cuando los datos se leen desde un archivo WAL, que no son datos actuales.
  • max_standby_streaming_delay - retraso utilizado para cancelar consultas cuando se reciben entradas WAL a través de la replicación de transmisión.

En general, si su servidor está diseñado para replicación de alta disponibilidad, desea mantener estos números cortos. La configuración predeterminada de 30000(milisegundos si no se dan unidades) es suficiente para esto. Sin embargo, si desea configurar algo como una réplica de archivo, informe o lectura que pueda tener consultas de larga duración, entonces querrá configurar esto en algo más alto para evitar consultas canceladas. La 900sconfiguración recomendada arriba parece un buen punto de partida. No estoy de acuerdo con los documentos oficiales sobre establecer un valor infinito -1como una buena idea, que podría enmascarar algunos códigos defectuosos y causar muchos problemas.

La única advertencia sobre las consultas de larga duración y el establecimiento de estos valores más altos es que otras consultas que se ejecutan en el esclavo en paralelo con la de larga duración que está causando que la acción WAL se retrase verán datos antiguos hasta que se complete la consulta larga. Los desarrolladores deberán comprender esto y serializar las consultas que no deberían ejecutarse simultáneamente.

Para la explicación completa de cómo max_standby_archive_delayy max_standby_streaming_delaytrabajar y por qué, vaya aquí .

Artif3x
fuente
1

Del mismo modo, aquí hay una segunda advertencia a la elaboración de @ Artif3x de la excelente respuesta de @ max-malysh, ambas anteriores.

Con cualquier aplicación retrasada de transacciones del maestro, los seguidores tendrán una vista antigua y obsoleta de los datos. Por lo tanto, si bien proporciona tiempo para que finalice la consulta en el seguidor estableciendo max_standby_archive_delay y max_standby_streaming_delay tiene sentido, tenga en cuenta estas dos advertencias:

Si el valor del seguidor para la copia de seguridad termina siendo demasiado conflictivo con las consultas de alojamiento, una solución sería múltiples seguidores, cada uno optimizado para uno u otro.

Además, tenga en cuenta que varias consultas seguidas pueden hacer que la aplicación de las entradas wal se demore. Entonces, al elegir los nuevos valores, no es solo el momento para una sola consulta, sino una ventana móvil que comienza cada vez que comienza una consulta conflictiva y termina cuando finalmente se aplica la entrada wal.

Beto
fuente