Saltar al contenido

¿Cómo obtener el espacio libre en disco actual en Postgres?

Te doy la bienvenida a nuestro sitio, en este sitio vas a encontrar la resolución que estás buscando.

PostgreSQL actualmente no tiene funciones para exponer directamente el espacio en disco.

Por un lado, ¿qué disco? Una instancia de producción de PostgreSQL a menudo se ve así:

  • /pg/pg94/: un RAID6 de almacenamiento rápido y fiable en un controlador RAID BBU en modo WB, para los catálogos y datos más importantes
  • /pg/pg94/pg_xlog: un RAID1 rápido y confiable, para los registros de transacciones
  • /pg/tablespace-lowredundancy: RAID10 de almacenamiento rápido y económico para elementos como índices y UNLOGGED tablas que no le importa perder para que pueda usar almacenamiento de menor redundancia
  • /pg/tablespace-bulkdata: Un RAID6 o similar de almacenamiento magnético lento cercano a la línea utilizado para registros de auditoría antiguos, datos históricos, datos en su mayoría de escritura y otras cosas a las que puede ser más lento acceder.
  • Los registros de postgreSQL suelen volver a estar en otro lugar, pero si se llena, es posible que el sistema aún se detenga. Dónde depende de una serie de opciones de configuración, algunas de las cuales no se pueden ver en PostgreSQL, como las opciones de syslog.

Luego está el hecho de que el espacio “libre” no significa necesariamente que PostgreSQL pueda usarlo (piense en: cuotas de disco, espacio en disco reservado para el sistema) y el hecho de que bloques/bytes no es la única restricción, ya que muchos sistemas de archivos también tienen límites en el número de archivos (inodos).

¿Cómo funciona unSELECT pg_get_free_disk_space() ¿Reporta esto?

Conocer el espacio libre en disco podría ser un problema de seguridad. Si es compatible, es algo que solo estaría expuesto al superusuario, al menos.

Lo que tu poder hacer es usar un lenguaje procedimental que no sea de confianza como plpythonu para realizar llamadas al sistema operativo para interrogar al sistema operativo host para obtener información sobre el espacio en disco, utilizando consultas contra pg_catalog.pg_tablespace y usando el data_directory ajuste de pg_settings para descubrir dónde guarda PostgreSQL las cosas en el sistema operativo host. También debe verificar los puntos de montaje (unix / Mac) / puntos de unión (Windows) para descubrir si pg_xlog, etc., se encuentran en un almacenamiento separado. Sin embargo, esto todavía no te ayudará con el espacio para los registros.

Me gustaria tener un SELECT * FROM pg_get_free_diskspace que informó el espacio principal de datadir y cualquier punto de montaje o punto de unión dentro de él, como para pg_xlog o pg_clog, y también informó cada espacio de tabla y cualquier punto de montaje dentro de él. Sería una función de devolución de conjuntos. Alguien a quien le importe lo suficiente tendría que molestarse en implementarlo para todas las plataformas de destino sin embargo, y en este momento, nadie lo quiere lo suficiente como para hacer el trabajo.


Mientras tanto, si está dispuesto a simplificar sus necesidades:

  • Un sistema de archivos
  • El sistema operativo de destino es compatible con UNIX / POSIX como Linux
  • No hay ningún sistema de cuotas habilitado
  • No hay porcentaje de bloque reservado para la raíz
  • el agotamiento del inodo no es una preocupación

entonces tú puedes CREATE LANGUAGE plpython3u; y CREATE FUNCTION a LANGUAGE plpython3u función que hace algo como:

import os
st = os.statvfs(datadir_path)
return st.f_bavail * st.f_frsize

en una función que returns bigint y o toma datadir_path como argumento, o lo descubre haciendo una consulta SPI como SELECT setting FROM pg_settings WHERE name = 'data_directory' desde dentro de PL / Python.

Si también desea admitir Windows, consulte Espacio multiplataforma restante en el volumen con python. Sin embargo, usaría consultas de la Interfaz de administración de Windows (WMI) en lugar de usar ctypes para llamar a la API de Windows.

O puede usar esta función que alguien escribió en PL / Perlu para hacerlo usando df y mount análisis de salida de comandos, que probablemente solo funcionará en Linux, pero bueno, está escrito previamente.

Aquí tiene una manera simple de obtener espacio libre en el disco sin ningún lenguaje extendido, simplemente defina una función usando pgsql.

CREATE OR REPLACE FUNCTION sys_df() RETURNS SETOF text[]
LANGUAGE plpgsql $$
BEGIN
    CREATE TEMP TABLE IF NOT EXISTS tmp_sys_df (content text) ON COMMIT DROP;
    COPY tmp_sys_df FROM PROGRAM 'df | tail -n +2';
    RETURN QUERY SELECT regexp_split_to_array(content, 's+') FROM tmp_sys_df;
END;
$$;

Uso:

select * from sys_df();
                          sys_df                               
-------------------------------------------------------------------
 overlay,15148428,6660248,7695656,46%,/
 overlay,15148428,6660248,7695656,46%,/
 tmpfs,65536,0,65536,0%,/dev
 tmpfs,768284,0,768284,0%,/sys/fs/cgroup
 /dev/sda2,15148428,6660248,7695656,46%,/etc/resolv.conf
 /dev/sda2,15148428,6660248,7695656,46%,/etc/hostname
 /dev/sda2,15148428,6660248,7695656,46%,/etc/hosts
 shm,65536,8,65528,0%,/dev/shm
 /dev/sda2,15148428,6660248,7695656,46%,/var/lib/postgresql/data
 tmpfs,65536,0,65536,0%,/proc/kcore
 tmpfs,65536,0,65536,0%,/proc/timer_list
 tmpfs,65536,0,65536,0%,/proc/sched_debug
 tmpfs,768284,0,768284,0%,/sys/firmware
(13 rows)

Utilizando df $PGDATA | tail -n +2 en vez de df | tail -n +2 mientras guarda todos los datos en la misma ruta en el disco. En este caso, la función solo devuelve el uso del disco de una fila para la ruta $ PGDATA.

NOTA DE SEGURIDAD

PROGRAMA Puede ejecutar cualquier comando por shell, como una espada de dos filos. es mejor usar un comando fijo string, o al menos evitar pasar cualquier entrada de usuario en él. Ver detalle en el documento.

Aquí hay una implementación de plpython2u que hemos estado usando durante un tiempo.

-- NOTE this function is a security definer, so it carries the superuser permissions
-- even when called by the plebs.
-- (required so we can access the data_directory setting.)
CREATE OR REPLACE FUNCTION get_tablespace_disk_usage()
    RETURNS TABLE (
        path VARCHAR,
        bytes_free BIGINT,
        total_bytes BIGINT
    )
AS $$
import os

data_directory = plpy.execute("select setting from pg_settings where name='data_directory';")[0]['setting']
records = []

for t in plpy.execute("select spcname, spcacl, pg_tablespace_location(oid) as path from pg_tablespace"):
    if t['spcacl']:
        # TODO handle ACLs. For now only show public tablespaces.
        continue

    name = t['spcname']
    if name == 'pg_default':
        path = os.path.join(data_directory, 'default')
    elif name == 'pg_global':
        path = os.path.join(data_directory, 'global')
    else:
        path = t['path']

    # not all tablespaces actually seem to exist(?) in particular, pg_default.
    if os.path.exists(path):
        s = os.statvfs(path)
        total_bytes = s.f_blocks * s.f_frsize
        bytes_free = s.f_bavail * s.f_frsize

        records.append((path, bytes_free, total_bytes))

return records

$$ LANGUAGE plpython2u STABLE SECURITY DEFINER;

El uso es algo como:

SELECT path, bytes_free, total_bytes FROM get_tablespace_disk_usage();

Sección de Reseñas y Valoraciones

Si haces scroll puedes encontrar las referencias de otros programadores, tú además eres capaz mostrar el tuyo si te gusta.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags :

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *