

# Resolución de bloqueadores de vaciado identificables en RDS para PostgreSQL
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers"></a>

Autovacuum lleva a cabo vaciados de forma intensiva y reduce la antigüedad de los ID de transacción hasta situarlos por debajo del umbral especificado por el parámetro `autovacuum_freeze_max_age` de la instancia de RDS. Esta antigüedad se puede consultar mediante la métrica `MaximumUsedTransactionIDs` de Amazon CloudWatch.

Para encontrar la configuración de `autovacuum_freeze_max_age` (que tiene un valor predeterminado de 200 millones de ID de transacción) para una instancia de Amazon RDS, puede utilizar la siguiente consulta:

```
SELECT
    TO_CHAR(setting::bigint, 'FM9,999,999,999') autovacuum_freeze_max_age
FROM
    pg_settings
WHERE
    name = 'autovacuum_freeze_max_age';
```

Tenga en cuenta que `postgres_get_av_diag()` solo comprueba si hay bloqueadores de vaciado intensivo cuando la antigüedad supera el umbral de [autovacuum adaptativo](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AdaptiveAutoVacuuming) de Amazon RDS de 500 millones de ID de transacción. Para que `postgres_get_av_diag()` detecte los bloqueadores, el bloqueador debe tener al menos 500 millones de transacciones de antigüedad.

La función `postgres_get_av_diag()` identifica los siguientes tipos de bloqueadores:

**Topics**
+ [Instrucción activa](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Active_statement)
+ [Inactividad en la transacción](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Idle_in_transaction)
+ [Transacción preparada](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Prepared_transaction)
+ [Ranura de replicación lógica](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Logical_replication_slot)
+ [Réplicas de lectura](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Read_replicas)
+ [Tablas temporales](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Temporary_tables)

## Instrucción activa
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Active_statement"></a>

En PostgreSQL, una instrucción activa es una instrucción SQL que la base de datos está ejecutando actualmente. Incluye consultas, transacciones o cualquier operación en curso. Al realizar la supervisión mediante `pg_stat_activity`, la columna de estado indica que el proceso con el PID correspondiente está activo.

La función `postgres_get_av_diag()` muestra un resultado similar al siguiente cuando identifica una instrucción que resulta ser una instrucción activa.

```
blocker               | Active statement
database              | my_database
blocker_identifier    | SELECT pg_sleep(20000);
wait_event            | Timeout:PgSleep
autovacuum_lagging_by | 568,600,871
suggestion            | Connect to database "my_database", review carefully and you may consider terminating the process using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"SELECT pg_terminate_backend (29621);"}
```

**Acción sugerida**

Siguiendo las instrucciones de la columna `suggestion`, el usuario puede conectarse a la base de datos en la que se encuentra la instrucción activa y, tal como se especifica en la columna `suggested_action`, se recomienda revisar detenidamente la opción de finalizar la sesión. Si la finalización es segura, se puede utilizar la función `pg_terminate_backend()` para finalizar la sesión. Esta acción la puede realizar un administrador (como la cuenta maestra de RDS) o un usuario con el privilegio `pg_terminate_backend()` necesario.

**aviso**  
Al finalizar la sesión, se desharán (`ROLLBACK`) los cambios que haya realizado. En función de sus requisitos, es posible que quiera volver a ejecutar la instrucción. Sin embargo, se recomienda hacerlo únicamente después de que el proceso de autovacuum haya finalizado su operación de vaciado intensivo.

## Inactividad en la transacción
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Idle_in_transaction"></a>

El concepto de inactividad en una instrucción de transacción se refiere a cualquier sesión en la que se haya abierto una transacción explícita (por ejemplo, emitiendo una instrucción `BEGIN`), se haya realizado algún trabajo y se esté esperando a que el cliente pase más trabajo o dé la señal de finalización de la transacción emitiendo una instrucción `COMMIT`, `ROLLBACK` o `END` (lo que daría como resultado un `COMMIT` implícitamente).

La función `postgres_get_av_diag()` muestra un resultado similar al siguiente cuando identifica una instrucción `idle in transaction` como bloqueador.

```
blocker               | idle in transaction
database              | my_database
blocker_identifier    | INSERT INTO tt SELECT * FROM tt;
wait_event            | Client:ClientRead
autovacuum_lagging_by | 1,237,201,759
suggestion            | Connect to database "my_database", review carefully and you may consider terminating the process using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"SELECT pg_terminate_backend (28438);"}
```

**Acción sugerida**

Como se indica en la columna `suggestion`, puede conectarse a la base de datos en la que se encuentra la sesión de inactividad en la transacción y finalizar la sesión mediante la función `pg_terminate_backend()`. El usuario puede ser su usuario administrador (cuenta maestra de RDS) o un usuario con el privilegio `pg_terminate_backend()`.

**aviso**  
Al finalizar la sesión, se desharán (`ROLLBACK`) los cambios que haya realizado. En función de sus requisitos, es posible que quiera volver a ejecutar la instrucción. Sin embargo, se recomienda hacerlo únicamente después de que el proceso de autovacuum haya finalizado su operación de vaciado intensivo.

## Transacción preparada
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Prepared_transaction"></a>

PostgreSQL permite realizar transacciones que forman parte de una estrategia de confirmación de dos fases denominada [transacciones preparadas](https://www.postgresql.org/docs/current/sql-prepare-transaction.html). Se habilitan al establecer el parámetro `max_prepared_transactions` en un valor distinto de cero. Las transacciones preparadas han sido diseñadas para garantizar que una transacción sea duradera y permanezca disponible incluso después de que la base de datos se bloquee, se reinicie o se desconecte del cliente. Al igual que las transacciones normales, se les asigna un identificador de transacción y pueden afectar al autovacuum. Si se deja en un estado preparado, el autovacuum no puede realizar la congelación y podría provocar un reinicio del ID de transacción.

Cuando las transacciones se dejan preparadas indefinidamente sin que las resuelva un administrador de transacciones, se convierten en transacciones preparadas huérfanas. La única forma de solucionar este problema es confirmar o revertir la transacción mediante los comandos `COMMIT PREPARED` o `ROLLBACK PREPARED` respectivamente.

**nota**  
Tenga en cuenta que una copia de seguridad realizada durante una transacción preparada seguirá conteniendo esa transacción después de la restauración. Consulte la siguiente información sobre cómo localizar y cerrar dichas transacciones.

La función `postgres_get_av_diag()` muestra el siguiente resultado cuando identifica un bloqueador que es una transacción preparada.

```
blocker               | Prepared transaction
database              | my_database
blocker_identifier    | myptx
wait_event            | Not applicable
autovacuum_lagging_by | 1,805,802,632
suggestion            | Connect to database "my_database" and consider either COMMIT or ROLLBACK the prepared transaction using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"COMMIT PREPARED 'myptx';",[OR],"ROLLBACK PREPARED 'myptx';"}
```

**Acción sugerida**

Como se menciona en la columna de sugerencias, conéctese a la base de datos en la que se encuentre la transacción preparada. Sobre la base de la columna `suggested_action`, revise detenidamente si desea enviar una instrucción `COMMIT` o `ROLLBACK`, y realizar la acción correspondiente.

Para supervisar las transacciones preparadas en general, PostgreSQL ofrece una vista de catálogo llamada `pg_prepared_xacts`. Puede utilizar la siguiente consulta para buscar transacciones preparadas.

```
SELECT
    gid,
    prepared,
    owner,
    database,
    transaction AS oldest_xmin
FROM
    pg_prepared_xacts
ORDER BY
    age(transaction) DESC;
```

## Ranura de replicación lógica
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Logical_replication_slot"></a>

El propósito de una ranura de replicación es almacenar los cambios no consumidos hasta que se repliquen en un servidor de destino. Para obtener más información, consulte [Logical replication](https://www.postgresql.org/docs/current/logical-replication.html) de PostgreSQL.

Existen dos tipos de ranuras de replicación lógica.

**Ranuras de replicación lógica inactivas**

Cuando finaliza la replicación, los registros de transacciones no consumidas no se pueden eliminar y la ranura de replicación queda inactiva. Aunque un suscriptor no utilice actualmente una ranura de replicación lógica inactiva, esta permanece en el servidor, lo que provoca la retención de los archivos WAL y evita la eliminación de los registros de transacciones antiguos. Esto puede aumentar el uso del disco y, específicamente, impedir que autovacuum limpie las tablas del catálogo interno, ya que el sistema debe evitar que se sobrescriba la información de LSN. Si este problema no se soluciona, puede provocar una sobrecarga del catálogo, una degradación del rendimiento y un mayor riesgo de que se produzcan vaciados previos al reinicio, lo que podría causar tiempo de inactividad en las transacciones.

**Ranuras de replicación lógica activas pero lentas**

A veces, la eliminación de las tuplas inactivas del catálogo se retrasa debido a la degradación del rendimiento de la replicación lógica. Este retraso en la replicación ralentiza la actualización de `catalog_xmin` y puede provocar una sobrecarga del catálogo y un vaciado previo al reinicio.

La función `postgres_get_av_diag()` muestra un resultado similar al siguiente cuando encuentra una ranura de replicación lógica que funciona como bloqueador.

```
blocker               | Logical replication slot
database              | my_database
blocker_identifier    | slot1
wait_event            | Not applicable
autovacuum_lagging_by | 1,940,103,068
suggestion            | Ensure replication is active and resolve any lag for the slot if active. If inactive, consider dropping it using the command in suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"SELECT pg_drop_replication_slot('slot1') FROM pg_replication_slots WHERE active = 'f';"}
```

**Acción sugerida**

Para resolver este problema, compruebe la configuración de la replicación para ver si hay problemas con el esquema o los datos de destino que puedan estar finalizando el proceso de aplicación. Los motivos más comunes son los siguientes: 
+ Columnas faltantes
+ Tipos de datos incompatibles
+ Discrepancia de datos
+ Tabla faltante

Si el problema está relacionado con problemas de infraestructura:
+ Problemas de red: [¿cómo resuelvo los problemas con una base de datos de Amazon RDS en un estado de red incompatible?](https://repost.aws/knowledge-center/rds-incompatible-network)
+ La base de datos o la instancia de base de datos no están disponibles por una de las siguientes razones:
  + La instancia de réplica se ha quedado sin espacio de almacenamiento: consulte qué hacer cuando [las instancias de base de datos de Amazon RDS se quedan sin almacenamiento](https://repost.aws/knowledge-center/rds-out-of-storage) para obtener información sobre cómo añadir almacenamiento.
  + Parámetros incompatibles: revise [¿Cómo puedo corregir una instancia de base de datos de Amazon RDS que está estancada en el estado parámetros incompatibles?](https://repost.aws/knowledge-center/rds-incompatible-parameters) para obtener más información acerca de cómo solucionar este problema.

Si la instancia está fuera de la red de AWS o en AWS EC2, consulte a su administrador sobre cómo resolver los problemas relacionados con la disponibilidad o la infraestructura.

**Eliminación de la ranura inactiva**

**aviso**  
Precaución: Antes de eliminar una ranura de replicación, asegúrese exhaustivamente de que no tenga ninguna replicación en curso, de que esté inactiva y de que se encuentre en un estado irrecuperable. Si se elimina una ranura de forma prematura, se podría interrumpir la replicación o provocar la pérdida de datos.

Después de confirmar que la ranura de replicación ya no es necesaria, elimínela para permitir que el autovacuum continúe. La condición `active = 'f'` garantiza que solo se eliminará una ranura inactiva.

```
SELECT pg_drop_replication_slot('slot1') WHERE active ='f'
```

## Réplicas de lectura
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Read_replicas"></a>

Cuando la configuración `hot_standby_feedback` está habilitada para las [réplicas de lectura de Amazon RDS](USER_PostgreSQL.Replication.ReadReplicas.md), evita que el autovacuum de la base de datos principal elimine determinadas filas inactivas que podrían seguir necesitando las consultas que se ejecuten en la réplica de lectura. Esto afecta a todos los tipos de réplicas de lectura físicas, incluidas las que se administran con o sin ranuras de replicación. Este comportamiento es necesario porque las consultas que se ejecutan en la réplica en espera requieren que esas filas permanezcan disponibles en el servidor principal, lo que evita cancelaciones y [conflictos de consultas](https://www.postgresql.org/docs/current/hot-standby.html#HOT-STANDBY-CONFLICT).

**Réplica de lectura con ranura de replicación física**  
Las réplicas de lectura con ranuras de replicación físicas mejoran considerablemente la fiabilidad y la estabilidad de la replicación en RDS para PostgreSQL. Estas ranuras garantizan que la base de datos principal conserve los archivos de registro de escritura anticipada esenciales hasta que la réplica los procese, ya que esto mantiene la coherencia de datos incluso durante las interrupciones de la red.

A partir de la versión 14 de RDS para PostgreSQL, todas las réplicas utilizan ranuras de replicación. En las versiones anteriores, solo las réplicas entre regiones utilizaban ranuras de replicación.

La función `postgres_get_av_diag()` muestra un resultado similar al siguiente cuando encuentra una réplica de lectura con una ranura de replicación física como bloqueador.

```
blocker               | Read replica with physical replication slot
database              |
blocker_identifier    | rds_us_west_2_db_xxxxxxxxxxxxxxxxxxxxx
wait_event            | Not applicable
autovacuum_lagging_by | 554,080,689
suggestion            | Run the following query on the replica "rds_us_west_2_db_xxxxxxxxxxxxxxxxxxxx" to find the long running query:                           
                      | SELECT * FROM pg_catalog.pg_stat_activity WHERE backend_xmin::text::bigint = 757989377;                                                       
                      | Review carefully and you may consdier terminating the query on read replica using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.                                 +                      |
suggested_action      | {"SELECT pg_terminate_backend(pid) FROM pg_catalog.pg_stat_activity WHERE backend_xmin::text::bigint = 757989377;","                                                                                 +
                      | [OR]                                                                                                                                                                                                 +
                      | ","Disable hot_standby_feedback","                                                                                                                                                                   +
                      | [OR]                                                                                                                                                                                                 +
                      | ","Delete the read replica if not needed"}
```

**Réplica de lectura con replicación de streaming**  
Amazon RDS permite configurar réplicas de lectura sin una ranura de replicación física en versiones anteriores, hasta la versión 13. Este enfoque reduce la sobrecarga al permitir que el servidor principal recicle los archivos WAL de forma más intensiva, lo que resulta ventajoso en entornos con limitaciones del espacio en disco y en los que se pueda tolerar un ReplicaLag ocasional. Sin embargo, sin no dispone de una ranura, la réplica en espera debe permanecer sincronizada para evitar que se pierdan archivos WAL. Amazon RDS utiliza archivos WAL archivados para ayudar a la réplica a ponerse al día en caso de que se quede atrás, pero este proceso requiere una supervisión exhaustiva y puede resultar lento.

La función `postgres_get_av_diag()` muestra un resultado similar al siguiente cuando encuentra una réplica de lectura de streaming como bloqueador.

```
blocker               | Read replica with streaming replication slot
database              | Not applicable
blocker_identifier    | xx.x.x.xxx/xx
wait_event            | Not applicable
autovacuum_lagging_by | 610,146,760
suggestion            | Run the following query on the replica "xx.x.x.xxx" to find the long running query:                                                                                                                                                         +
                      | SELECT * FROM pg_catalog.pg_stat_activity WHERE backend_xmin::text::bigint = 348319343;                                                                                                                                                     +
                      | Review carefully and you may consdier terminating the query on read replica using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.                                       +
                      |
suggested_action      | {"SELECT pg_terminate_backend(pid) FROM pg_catalog.pg_stat_activity WHERE backend_xmin::text::bigint = 348319343;","                                                                                                                        +
                      | [OR]                                                                                                                                                                                                                                        +
                      | ","Disable hot_standby_feedback","                                                                                                                                                                                                          +
                      | [OR]                                                                                                                                                                                                                                        +
                      | ","Delete the read replica if not needed"}
```

**Acción sugerida**

Como se recomienda en la columna `suggested_action`, revise detenidamente estas opciones para desbloquear el autovacuum.
+ **Finalizar la consulta**: de acuerdo con las instrucciones de la columna de sugerencias, puede conectarse a la réplica de lectura, tal y como se especifica en la columna suggested\$1action. Se recomienda revisar detenidamente la opción para finalizar la sesión. Si la finalización se considera segura, se puede utilizar la función `pg_terminate_backend()` para finalizar la sesión. Esta acción la puede realizar un administrador (como la cuenta maestra de RDS) o un usuario con el privilegio pg\$1terminate\$1backend() necesario.

  Puede ejecutar el siguiente comando SQL en la réplica de lectura para finalizar la consulta que impide que el proceso de vaciado en el principal pueda limpiar las filas antiguas. El valor de `backend_xmin` se indica en la salida de la función:

  ```
  SELECT
      pg_terminate_backend(pid)
  FROM
      pg_catalog.pg_stat_activity
  WHERE
      backend_xmin::text::bigint = backend_xmin;
  ```
+ **Desactivar la retroalimentación de espera activa**: plantéese deshabilitar el parámetro `hot_standby_feedback` si provoca retrasos significativos en el vaciado.

  El parámetro `hot_standby_feedback` permite que una réplica de lectura informe al servidor principal sobre su actividad de consulta, lo que evita que el principal vacíe las tablas o filas que están en uso en la réplica en espera. Si bien esto garantiza la estabilidad de las consultas en la réplica en espera, puede retrasar considerablemente el vaciado en el principal. La desactivación de esta característica permite al servidor principal continuar con el vaciado sin tener que esperar a que la réplica en espera se ponga al día. Sin embargo, esto puede provocar cancelaciones o errores en las consultas en la réplica en espera si intenta acceder a las filas que ha vaciado el principal.
+ **Eliminar la réplica de lectura si no es necesaria**: si la réplica de lectura ya no es necesaria, puede eliminarla. Esto eliminará la sobrecarga de replicación asociada y permitirá que el servidor principal recicle los registros de transacciones sin que la réplica se lo obstaculice.

## Tablas temporales
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Temporary_tables"></a>

Las [tablas temporales](https://www.postgresql.org/docs/current/sql-createtable.html), que se crean con la palabra clave `TEMPORARY`, residen en el esquema temporal (por ejemplo, pg\$1temp\$1xxx) y solo la sesión que las haya creado puede acceder a ellas. Las tablas temporales se eliminan al finalizar la sesión. Sin embargo, estas tablas son invisibles para el proceso de autovacuum de PostgreSQL y la sesión que las haya creado debe vaciarlas manualmente. Intentar vaciar la tabla temporal desde otra sesión no tiene ningún efecto.

En circunstancias poco habituales, puede existir una tabla temporal sin que sea propiedad de una sesión activa. Si la sesión propietaria finaliza inesperadamente debido a un bloqueo grave, un problema de red o un suceso similar, es posible que la tabla temporal no se limpie y quede como una tabla “huérfana”. Cuando el proceso de autovacuum de PostgreSQL detecta una tabla temporal huérfana, registra el siguiente mensaje:

```
LOG: autovacuum: found orphan temp table \"%s\".\"%s\" in database \"%s\"
```

La función `postgres_get_av_diag()` muestra un resultado similar al siguiente cuando identifica una tabla temporal como bloqueador. Para que la función muestre correctamente el resultado relacionado con las tablas temporales, debe ejecutarse en la misma base de datos en la que se encuentren esas tablas.

```
blocker               | Temporary table
database              | my_database
blocker_identifier    | pg_temp_14.ttemp
wait_event            | Not applicable
autovacuum_lagging_by | 1,805,802,632
suggestion            | Connect to database "my_database". Review carefully, you may consider dropping temporary table using command in suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"DROP TABLE ttemp;"}
```

**Acción sugerida**

Siga las instrucciones que aparecen en la columna `suggestion` del resultado para identificar y eliminar la tabla temporal que impide la ejecución del autovacuum. Use el siguiente comando para eliminar la tabla temporal notificada por `postgres_get_av_diag()`. Reemplace el nombre de la tabla en función del resultado proporcionado por la función `postgres_get_av_diag()`.

```
DROP TABLE my_temp_schema.my_temp_table;
```

La siguiente consulta se puede utilizar para identificar tablas temporales:

```
SELECT
    oid,
    relname,
    relnamespace::regnamespace,
    age(relfrozenxid)
FROM
    pg_class
WHERE
relpersistence = 't'
ORDER BY
    age(relfrozenxid) DESC;
```