¿Por qué he recibido el error «No queda espacio en el dispositivo» o «DiskFull» en Amazon RDS para PostgreSQL?

11 minutos de lectura
0

Tengo un Amazon Relational Database Service (Amazon RDS) pequeño para una base de datos de PostgreSQL. El espacio de almacenamiento libre de la instancia está disminuyendo y recibo el siguiente error: «Mensaje de error: PG::DiskFull: ERROR: no se pudo extender el archivo "base/16394/5139755": No queda espacio en el dispositivo. SUGERENCIA: Compruebe el espacio libre en disco.» Quiero resolver los errores de DiskFull y evitar problemas de almacenamiento.

Descripción breve

El almacenamiento de instancias de base de datos de Amazon RDS lo utilizan:

  • Tablas o archivos temporales que se crean mediante transacciones de PostgreSQL
  • Archivos de datos
  • Registros de escritura previa (registros WAL)
  • Ranuras de replicación
  • Registros de base de datos (archivos de errores) que se conservan durante demasiado tiempo
  • Otros archivos de base de datos o Linux que admitan el estado coherente de la instancia de base de datos de RDS

Resolución

1.Utilice Amazon CloudWatch para supervisar el espacio de almacenamiento de la base de datos mediante la métrica FreeStorageSpace. Al configurar una alarma de CloudWatch para obtener espacio de almacenamiento libre, recibirá una notificación cuando el espacio comience a disminuir. Si recibe una alarma, revise las causas de los problemas de almacenamiento mencionadas anteriormente.

2.Si la instancia de base de datos sigue consumiendo más almacenamiento del esperado, compruebe lo siguiente:

  • Tamaño de los archivos de registro de la base de datos
  • Presencia de archivos temporales
  • Aumento constante del uso del disco en los registros de transacciones
  • Ranura de replicación:
  • Las ranuras de replicación física se crean mediante réplicas de lectura entre regiones o réplicas de lectura de la misma región solo si se ejecutan en PostgreSQL 14.1 y versiones superiores
  • Las ranuras de replicación lógica se crean para una réplica o un suscriptor
  • Tablas infladas o eliminación incorrecta de filas muertas
  • Presencia de archivos huérfanos

3.Cuando la carga de trabajo sea predecible, habilite el escalado automático del almacenamiento para la instancia. Con el escalado automático de almacenamiento activado, cuando Amazon RDS detecta que se está quedando sin espacio libre en la base de datos, el almacenamiento se escala automáticamente. Amazon RDS inicia una modificación de almacenamiento para una instancia de base de datos con el escalado automático habilitado cuando se dan los siguientes factores:

  • El espacio libre disponible es inferior al 10 por ciento del almacenamiento asignado.
  • El estado de almacenamiento bajo dura al menos cinco minutos.
  • Han pasado al menos seis horas desde la última modificación del almacenamiento o la optimización del almacenamiento se ha completado en la instancia, lo que dure más.

Puede establecer un límite para el escalado automático de la instancia de base de datos estableciendo el umbral máximo de almacenamiento. Para obtener más información, consulte Administrar la capacidad automáticamente con el escalado automático del almacenamiento de Amazon RDS.

Comprobar el tamaño de los archivos de registro de la base de datos

De forma predeterminada, los archivos de registro de errores de Amazon RDS para PostgreSQL tienen un valor de retención de 4320 minutos (tres días). Los archivos de registro de gran tamaño pueden ocupar más espacio debido al aumento de las cargas de trabajo o al registro excesivo. Puede cambiar el período de retención de los registros del sistema mediante el parámetro rds.log_retention_period del grupo de parámetros de la base de datos asociado a la instancia de base de datos. Por ejemplo, si establece el valor en 1440, los registros se conservarán durante un día. Para obtener más información, consulte Archivos de registro de bases de datos de PostgreSQL.

Además, puede cambiar los parámetros de registro e informes de errores en el grupo de parámetros de la base de datos para reducir el registro excesivo. Esto, a su vez, reduce el tamaño del archivo de registros. Para obtener más información, consulte Informes y registro de errores.

Comprobar si hay archivos temporales

Los archivos temporales son archivos que se almacenan por backend o conexión de sesión. Estos archivos se utilizan como grupo de recursos. Revise las estadísticas de los archivos temporales ejecutando un comando similar al siguiente:

psql=> SELECT datname, temp_files AS "Temporary files",temp_bytes AS "Size of temporary files" FROM pg_stat_database ;

**Importante:**Las columnas temp_files y temp_bytes en la vista pg_stat_database recopilan estadísticas agregadas (acumulativas). Esto se debe a que estos contadores solo se restablecen mediante la recuperación al iniciar el servidor. Es decir, los contadores se restablecen después de un apagado inmediato, un bloqueo del servidor o una recuperación a un momento dado (PITR). Por este motivo, se recomienda supervisar el crecimiento de estos archivos en número y tamaño, en lugar de revisar solo el resultado.

Los archivos temporales se crean para clasificaciones, hashes o resultados de consultas temporales. Para hacer un seguimiento de la creación de tablas o archivos temporales, establezca log_temp_files en un grupo de parámetros personalizado. Este parámetro controla el registro de los nombres y tamaños de los archivos temporales. Si establece el valor log_temp_files en 0, se registrará toda la información del archivo temporal. Si establece el parámetro en un valor positivo, solo se registrarán los archivos que sean iguales o superiores al número especificado de kilobytes. La configuración predeterminada es -1, que deshabilita el registro de archivos temporales.

También puede usar un EXPLAIN ANALYZE de su consulta para revisar la clasificación de los discos. Al revisar el resultado del registro, puede ver el tamaño de los archivos temporales creados por la consulta. Para obtener más información, consulte la documentación de PostgreSQL para Supervisar la actividad de la base de datos.

Comprobar si hay un aumento constante en el uso del disco en los registros de transacciones

La métrica de CloudWatch para TransactionLogsDiskUsage representa el espacio en disco que utilizan los registros WAL de transacciones. El aumento en el uso del disco de registros de transacciones puede ocurrir debido a:

  • Cargas elevadas de base de datos (escrituras y actualizaciones que generan más registros WAL)
  • Retraso de réplica de lectura de transmisión (réplicas en la misma región) o réplica de lectura en estado de almacenamiento lleno
  • Ranuras de replicación

Las ranuras de replicación se pueden crear como parte de la función de decodificación lógica de AWS Database Migration Service (AWS DMS). Para la replicación lógica, el parámetro de ranura rds.logical_replication se establece en 1. Las ranuras de replicación retienen los archivos de registros WAL hasta que un consumidor los consuma externamente. Por ejemplo, pueden consumirlos pg_recvlogical, trabajos de extracción, transformación y carga (ETL) o AWS DMS.

Si establece el valor del parámetro rds.logical_replication en 1, AWS RDS establece los parámetros wal_level, max_wal_senders, max_replication_slots y max_connections. Cambiar estos parámetros puede aumentar la generación de registros WAL. Se recomienda configurar el parámetro rds.logical_replication solo cuando utilice ranuras lógicas. Si este parámetro se establece en 1 y hay ranuras de replicación lógica, pero no hay un consumidor para los archivos de registros WAL retenidos en la ranura de replicación, el uso del disco de los registros de transacciones puede aumentar. Esto también se traduce en una disminución constante del espacio de almacenamiento libre.

Ejecute esta consulta para confirmar la presencia y el tamaño de las ranuras de replicación:

PostgreSQL v9:

psql=> SELECT slot_name, pg_size_pretty(pg_xlog_location_diff(pg_current_xlog_location(),restart_lsn)) AS
replicationSlotLag, active FROM pg_replication_slots ;

PostgreSQL v10 y versiones posteriores:

psql=> SELECT slot_name, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(),restart_lsn)) AS replicationSlotLag,
active FROM pg_replication_slots ;

Tras identificar la ranura de replicación que no se está consumiendo (con un estado activo que es False), elimine la ranura de replicación ejecutando esta consulta:

psql=> SELECT pg_drop_replication_slot('Your_slotname_name');

Nota: Si una tarea de AWS DMS es el consumidor y ya no es necesaria, elimínela y elimine manualmente la ranura de replicación.

Ejemplo de salida:

slot_name                                                      | replicationslotlag | active
---------------------------------------------------------------+--------------------+--------
xc36ujql35djp_00013322_907c1e0a_9f8b_4c13_89ea_ef0ea1cf143d    | 129 GB             | f
7pajuy7htthd7sqn_00013322_a27bcebf_7d0f_4124_b336_92d0fb9f5130 | 704 MB             | t
zp2tkfo4ejw3dtlw_00013322_03e77862_689d_41c5_99ba_021c8a3f851a | 624 MB             | t

En este ejemplo, el nombre de ranura xc36ujql35djp_00013322_907c1e0a_9f8b_4c13_89ea_ef0ea1cf143d tiene un estado activo que es False. Por lo tanto, esta ranura no se usa activamente y contribuye a almacenar 129 GB de archivos de transacciones.

Ejecute el siguiente comando para eliminar la consulta:

psql=> SELECT pg_drop_replication_slot('xc36ujql35djp_00013322_907c1e0a_9f8b_4c13_89ea_ef0ea1cf143d');

Comprobar el estado de las réplicas de lectura entre regiones

Al utilizar la replicación de lectura entre regiones, se crea una ranura de replicación física en la instancia principal. Si se produce un error en la réplica de lectura entre regiones, el espacio de almacenamiento de la instancia de base de datos principal puede verse afectado. Esto ocurre porque los archivos de registros WAL no se replican en la réplica de lectura. Puede utilizar las métricas de CloudWatch, el retraso en la ranura de replicación más antigua y el uso del disco de los registros de transacciones para determinar el retraso de la réplica más retrasada. También puede ver cuánto espacio de almacenamiento se utiliza para los datos de WAL.

Para comprobar el estado de la réplica de lectura entre regiones, utilice la consulta pg_replication_slots. Para obtener más información, consulte la documentación de PostgreSQL para pg_replication_slots. Si el estado activo se devuelve como false, la ranura no se utiliza actualmente para la replicación.

psql=> SELECT * FROM pg_replication_slots;

También puede usar la vista pg_stat_replication en la instancia de origen para comprobar las estadísticas de la replicación. Para obtener más información, consulte la documentación de PostgreSQL para pg_stat_replication.

Comprobar si hay tablas infladas o si la eliminación de filas muertas es incorrecta (tuplas)

En las operaciones normales de PostgreSQL, las filas muertas que se eliminan o quedan obsoletas debido a una operación UPDATE no se eliminan de la tabla. Para las implementaciones del Control de concurrencia multiversión (MVCC), cuando se lleva a cabo una operación DELETE, la fila no se elimina inmediatamente del archivo de datos. En su lugar, la fila se marca como eliminada configurando el campo xmax en un encabezado. Las actualizaciones marcan primero las filas para eliminarlas y, a continuación, llevan a cabo una operación de inserción. Esto permite la concurrencia con un bloqueo mínimo entre las diferentes transacciones. Como resultado, se mantienen diferentes versiones de filas como parte del proceso de MVCC.

Si las filas muertas no se eliminan, pueden permanecer en los archivos de datos pero ser invisibles para cualquier transacción, lo que afecta al espacio en disco. Si una tabla tiene muchas operaciones DELETE y UPDATE, las filas muertas pueden ocupar una gran cantidad de espacio en disco. Estas tablas se dice que están «infladas» en PostgreSQL.

La operación VACUUM puede liberar el almacenamiento utilizado por las filas muertas para que pueda reutilizarse, pero esto no libera el almacenamiento libre en el sistema de archivos. Al ejecutar VACUUM FULL, se libera el almacenamiento en el sistema de archivos. Sin embargo, tenga en cuenta que durante el tiempo de ejecución de VACUUM FULL, se mantiene un bloqueo de acceso exclusivo en la tabla. Este método también requiere espacio adicional en el disco porque escribe una nueva copia de la tabla y no libera la copia anterior hasta que se complete la operación. Se recomienda utilizar este método solo cuando deba recuperar una cantidad significativa de espacio dentro de la tabla. También se recomienda hacer operaciones periódicas de «vacuum» o «autovacuum» en tablas que se actualicen con frecuencia. Para obtener más información, consulte la documentación de PostgreSQL para VACUUM.

Para comprobar el número estimado de filas muertas, utilice la vista pg_stat_all_tables. Para obtener más información, consulte la documentación de PostgreSQL para Vista pg_stat_all_tables. En este ejemplo, hay 1999952 filas muertas (n_dead_tup):

psql => SELECT * FROM pg_stat_all_tables WHERE relname='test';

-[ RECORD 1 ]-------+------------------------------
relid               | 16395
schemaname          | public
relname             | test
seq_scan            | 3
seq_tup_read        | 5280041
idx_scan            |
idx_tup_fetch       |
n_tup_ins           | 2000000
n_tup_upd           | 0
n_tup_del           | 3639911
n_tup_hot_upd       | 0
n_live_tup          | 1635941
n_dead_tup          | 1999952
n_mod_since_analyze | 3999952
last_vacuum         |
last_autovacuum     | 2018-08-16 04:49:52.399546+00
last_analyze        | 2018-08-09 09:44:56.208889+00
last_autoanalyze    | 2018-08-16 04:50:22.581935+00
vacuum_count        | 0
autovacuum_count    | 1
analyze_count       | 1
autoanalyze_count   | 1


psql => VACUUM TEST;

Comprobar si hay archivos huérfanos

Los archivos huérfanos pueden aparecer cuando están presentes en el directorio de la base de datos, pero no hay objetos que apunten a esos archivos. Esto puede ocurrir si la instancia se queda sin espacio de almacenamiento o si el motor se bloquea durante una operación como ALTER TABLE, VACUUM FULL o CLUSTER. Para comprobar si hay archivos huérfanos, siga estos pasos:

1.Inicie sesión en PostgreSQL en cada base de datos.

2.Ejecute estas consultas para evaluar los tamaños usados y reales.

# Size of the database occupied by files
psql=> SELECT pg_size_pretty(pg_database_size('DATABASE_NAME'));

# Size of database retrieved by summing the objects (real size)
psql=> SELECT pg_size_pretty(SUM(pg_relation_size(oid))) FROM pg_class;

3.Anote los resultados. Si la diferencia es significativa, es posible que los archivos huérfanos estén utilizando espacio de almacenamiento.


Información relacionada

Trabajar con réplicas de lectura para Amazon RDS para PostgreSQL

Herramientas de supervisión automatizadas