PostgreSQL - 查询当前正在进行vacuum操作的表的方法?

8
我找到了一个查询可以查看已运行的vacuum,但无法查看当前正在运行的vacuum。(http://heatware.net/databases/postgres-tables-auto-vacuum-analyze/
是否有一种查询可以实现这个功能?我知道我可以使用pg_stat_activity,但有些vacuum没有表名,而是使用pg_toast.pg_toast_3621837,这种方法并不能100%有效。

我相信你可以在这里找到你问题的答案:https://dev59.com/AWMl5IYBdhLWcg3wXWET - Zeki
我不知道有什么简单/预制的东西。Zeki提供了一种方法来确定一个toast表与哪个基本表相关联。但我很好奇...为什么?你想通过这样做实现什么目标? - Craig Ringer
我在我的Rails项目中有一个庞大的“耙”任务,我不想在吸尘器运行时启动它。该查询需要几个小时才能运行,如果正在运行吸尘器,则数据库负载会急剧增加。 - Geesu
2个回答

6
这个问题可以通过系统目录轻松解决。我建议加入pg_locks进行连接,因为autovacuum在处理表时会获取ShareUpdateExclusiveLock锁,以避免从pg_stat_activity中手动解析查询。下面的查询列出正在自动清理的表格,解决了对pg_toast引用的问题,如果正在清理toast表,就像@Zeki链接到的Postgres pg_toast in autovacuum - which table?提问中所解释的那样。
SELECT n.nspname || '.' || c.relname
    FROM pg_namespace n, pg_stat_activity a, pg_locks l, pg_class c
    WHERE
        a.query LIKE 'autovacuum: %'
        AND l.pid = a.pid
        AND l.mode = 'ShareUpdateExclusiveLock'
        AND (c.oid = l.relation OR c.reltoastrelid = l.relation)
        AND n.oid = c.relnamespace
        AND n.nspname <> 'pg_toast';

请注意,虽然 pg_stat_activitypg_locks 目录在多个数据库中共享,但是该查询只会列出当前数据库中正在自动清理的表,因为 pg_relation 不是共享目录。

2

不要查找表是否正在进行清理,而是关闭涉及表的自动清理功能:

alter table table_name_pattern 
set (
    autovacuum_enabled = false,
    toast.autovacuum_enabled = false
);
模式是像tbl*
这样的全局匹配模式。在查询结束时,自动清理打开。
alter table table_name_pattern 
set (
    autovacuum_enabled = true,
    toast.autovacuum_enabled = true
);

根据评论进行编辑:

查询涉及的表是否正在被清理是不必要且无用的。如果已知一个或多个涉及的表正在被清理,那么应该怎么做?等待并重复查询直到没有任何表在被清理?然后再开始长时间的查询,只是发现自动清理又重新启动了?这没有意义。为什么不直接关闭自动清理并避免所有麻烦呢?

在使用方法上,没有通过困难的方式就具有道德优越性,特别是如果通过困难的方式得到的结果比简单方式更差。简单的代码更易于使用和理解,但构建起来不一定更容易。很多时候恰好相反,需要更多的智力努力或准备工作。


如果在事务内更改自动清理设置,并且该事务被回滚,则该设置将恢复到事务开始前的状态。

drop table if exists t;
create table t (id int);

begin;

alter table t
set (
    autovacuum_enabled = false,
    toast.autovacuum_enabled = false
);

\d+ t
                          Table "public.t"
 Column |  Type   | Modifiers | Storage | Stats target | Description 
--------+---------+-----------+---------+--------------+-------------
 id     | integer |           | plain   |              | 
Has OIDs: no
Options: autovacuum_enabled=false

rollback;

\d+ t
                          Table "public.t"
 Column |  Type   | Modifiers | Storage | Stats target | Description 
--------+---------+-----------+---------+--------------+-------------
 id     | integer |           | plain   |              | 
Has OIDs: no

但是,在事务内部设置的参数在事务外部不可见,所以我猜自动清理仍然会运行。如果这是真的,那么设置必须在事务之外完成,并由一个作业控制,无论长时间运行的查询发生什么情况,都将其恢复为原来的设置。


@Kirk,这并没有直接回答问题所问,但是它解决了评论中所阐述的问题。无论如何感谢您的点赞。 - Clodoaldo Neto
赏金的目的是鼓励有人去完成编写“困难”的查询的工作。您的回答很有帮助并且受到赞赏,但是忽略了赏金的重点。也许@Geesu会接受您的答案,因为它适用于他。 - Kirk Roybal
@Kirk 根据您的评论进行了编辑。 - Clodoaldo Neto
“不必要和无用”...那是一个观点问题。你真的了解每种可能的情况,并准备好说没有人可能有一个你没有考虑过的用例吗?如果是这样,我建议你去Ubuntu论坛,尽管随意地写下“RTFM”和“你不需要那个”的回答。这些答案在SO上是不合适的。“没有道德优越性”...那是一个个人评论和性格假设,也不应该出现在SO上。 - Kirk Roybal
@ClodoaldoNeto 谢谢。 - ArtemGr
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接