查看原文
其他

空间都去哪里了?(上)

xiongcc PostgreSQL学徒 2023-12-03

前言

今天是PostgreSQL数据库生态大会的第二天,诸位演讲嘉宾共同带来了一场精彩纷呈的技术盛宴,在会场也碰到了很多老朋友与数据库圈的前辈,收获颇丰。

回到文章主题,起因是在③群中,一位筒子提到:

库下面分配了 400 多个文件,通过 pg_class.oid 和 relfilenode 都没有查到,这种可能是什么什么情况导致的?

在确认库的 oid 是相符的之后,这个问题也就变成了 orphan files,即孤儿文件。这种孤儿文件是哪里来的?或者再做个发散,磁盘空间都消耗到哪里去了?空间都去哪里了?

分析

最开始以为是临时文件,在 14 以前的版本假如数据库崩了,临时文件是会保留的,因此极端情况下,多个实例都因为各种各样的原因崩了,比如 OOM,那就有临时文件将磁盘打爆的风险,索引在 14 中引入了一个 GUC——remove_temp_files_after_crash,在崩溃后删除相关临时文件,至于保留的目的则是为了 debug。

When set to on, which is the default, PostgreSQL will automatically remove temporary files after a backend crash. If disabled, the files will be retained and may be used for debugging, for example. Repeated crashes may however result in accumulation of useless files. This parameter can only be set in the postgresql.conf file or on the server command line.

默认设置为 "on "时,PostgreSQL 会在后端进程崩溃后自动删除临时文件。如果禁用,这些文件将被保留,并用于调试。不过,多次反复崩溃可能会导致无用文件的积累。

但临时文件位于 pgsql_tmp 目录下,所以不是这个原因。

那是什么原因呢?我首先想到的便是 orphan files,让我们看个常见的例子

postgres=# begin;
BEGIN
postgres=*# create table tt1(id int,info text);
CREATE TABLE
postgres=*# select pg_relation_filepath('tt1');
 pg_relation_filepath 
----------------------
 base/5/16995
(1 row)

postgres=*# insert into tt1 select n,md5(random()::text) from generate_series(1,100000) as n;
INSERT 0 100000
postgres=*# select pg_backend_pid();
 pg_backend_pid 
----------------
          32645
(1 row)

磁盘上已经有数据了

[postgres@xiongcc 5]$ ls -lrth 16995
-rw------- 1 postgres postgres 6.6M Nov  4 13:07 16995

现在让我们模拟数据库崩了,OOM了

[postgres@xiongcc 5]$ kill -9 32645

postgres=*# select 1;
server closed the connection unexpectedly
        This probably means the server terminated abnormally
        before or while processing the request.
The connection to the server was lost. Attempting reset: Succeeded.

这个时候你再去看,就可以看到类似的现象了,和磁盘上对不上了。

postgres=# select relname from pg_class where oid = 16995 or relfilenode = 16995;
 relname 
---------
(0 rows)

[postgres@xiongcc 5]$ ls -lrth 16995
-rw------- 1 postgres postgres 6.6M Nov  4 13:10 16995

对于这种现象你没有太好的办法,只能通过定时巡检人肉检查,比如通过如下查询检查那些在 pg_class 中没有对应条目的文件。

SELECT
    *
FROM
    pg_ls_dir('/home/postgres/16data/base/5'AS file
WHERE
    file ~ '^[0-9]*'
    AND file::text NOT IN (
        SELECT
            oid::text
        FROM
            pg_class);

类似的,像 CREATE TABLE ... AS 或者 vacuum full 等操作,遇到了异常宕机,错误退出的情况,都会留下类似现象。

小结

That's all,马上下午场要开始了,我要继续主持下午场了 ~

后面继续我们的话题,空间都去哪里了?(下篇),与各位聊聊各种奇奇怪怪的空间消耗。

参考

https://dba.stackexchange.com/questions/306203/reclaim-space-after-a-failed-vacuum-full


继续滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存