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 yUNLOGGED
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.