如何获得Postgres中当前的可用磁盘空间?

Chr*_*ian 10 sql api postgresql diskspace postgresql-9.3

在开始在我的数据库中做一些工作之前,我需要确保我至少有1Gb的可用磁盘空间.我正在寻找这样的东西:

select pg_get_free_disk_space();
Run Code Online (Sandbox Code Playgroud)

可能吗?(我在docs中找不到任何相关内容).

PG:9.3和OS:Linux/Windows

Cra*_*ger 12

PostgreSQL目前没有直接暴露磁盘空间的功能.

一方面,哪个磁盘?生产PostgreSQL实例通常如下所示:

  • /pg/pg94/:WBU模式下BBU RAID控制器上的快速可靠存储RAID6,用于目录和最重要的数据
  • /pg/pg94/pg_xlog:一个快速可靠的RAID1,用于事务日志
  • /pg/tablespace-lowredundancy:用于索引和UNLOGGED表格之类的快速廉价存储的RAID10 ,您不必担心丢失,因此您可以使用较低冗余的存储
  • /pg/tablespace-bulkdata:RAID6或类似的慢速近线磁存储,用于旧审计日志,历史数据,写入数据以及其他可能较慢访问的内容.
  • postgreSQL日志通常在其他地方再次出现,但如果这个日期填满,系统可能仍会停止.哪里取决于许多配置设置,其中一些根本不能从PostgreSQL中看到,比如syslog选项.

然后就是"自由"空间并不一定意味着PostgreSQL可以使用它(想想:磁盘配额,系统保留磁盘空间),以及空闲/字节不是唯一约束的事实,就像许多文件系统一样对文件数量(inode)也有限制.

怎么SELECT pg_get_free_disk_space()报告这个?

了解可用磁盘空间可能是一个安全问题.如果受到支持,那么它至少只会暴露给超级用户.

可以做的是使用不受信任的过程语言,例如plpythonu进行操作系统调用以询问主机操作系统的磁盘空间信息,使用查询pg_catalog.pg_tablespace和使用该data_directory设置pg_settings来发现PostgreSQL在主机操作系统上保留内容的位置.您还必须检查挂载点(unix/Mac)/交接点(Windows)以发现是否pg_xlog在单独的存储上.但是,这仍然无法真正帮助您获取日志空间.

我非常希望有一个SELECT * FROM pg_get_free_diskspace报告主数据库空间,以及其中的任何挂载点或连接点,如pg_xlogpg_clog,并且还报告每个表空间和其中的任何挂载点.这是一个回归功能.足够关心的人不得不费心去为所有目标平台实施它,而且现在,没有人希望它能够完成这项工作.


与此同时,如果您愿意将您的需求简化为:

  • 一个文件系统
  • 目标OS与Linux兼容,与UNIX/POSIX兼容
  • 没有启用配额系统
  • 没有根保留块百分比
  • inode耗尽不是一个问题

然后你可以CREATE LANGUAGE plpython3u;CREATE FUNCTION一个LANGUAGE plpython3u像以下一样的功能:

import os
st = os.statvfs(datadir_path)
return st.f_bavail * st.f_frsize
Run Code Online (Sandbox Code Playgroud)

在一个函数中returns bigint,或者datadir_path作为一个参数,或者通过像SELECT setting FROM pg_settings WHERE name = 'data_directory'PL/Python中那样执行SPI查询来发现它.

如果您也想支持Windows,请参阅使用python在卷上剩余的跨平台空间.我使用Windows管理界面(WMI)查询而不是使用ctypes来调用Windows API.

或者你可以使用有人在PL/Perlu中编写的这个函数来使用dfmount命令输出解析,这可能只适用于Linux,但是嘿,它是预先编写的.

  • 另一个选项可以是创建文本文件的cron作业,例如每x分钟包含可用空间信息.然后可以通过FDW表(或cron作业插入/更新包含信息的表中的行)使该文本文件可用. (2认同)

esh*_*han 12

这里有一个简单的方法来获取可用磁盘空间,无需任何扩展语言,只需使用 pgsql 定义一个函数即可。

CREATE OR REPLACE FUNCTION sys_df() RETURNS SETOF text[]
LANGUAGE plpgsql AS $$
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;
$$;
Run Code Online (Sandbox Code Playgroud)

函数使用:

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)
Run Code Online (Sandbox Code Playgroud)

在将所有数据保存在磁盘上同一路径中时使用df $PGDATA | tail -n +2而不是。df | tail -n +2在这种情况下,该函数仅返回 $PGDATA 路径的一行磁盘使用情况。

安全注意事项

PROGRAM可以通过shell运行任何命令,它就像一把两刃剑。最好使用固定的命令字符串,或者至少避免在其中传递任何用户输入。详细信息请参阅文档