【问题标题】:PostgreSQL - Query to determine which tables are currently being vacuumed?PostgreSQL - 查询以确定当前正在清理哪些表?
【发布时间】:2014-07-01 19:40:37
【问题描述】:

我找到了一个查询来查看真空吸尘器何时运行,但不是当前正在运行的。 (http://heatware.net/databases/postgres-tables-auto-vacuum-analyze/)

是否有查询可以完成此操作?我知道我可以点击 pg_stat_activity,但有些真空吸尘器没有表名,而是有 pg_toast.pg_toast_3621837,所以这不会 100% 起作用。

【问题讨论】:

  • 相信你可以在这里找到问题的答案:stackoverflow.com/questions/18456026/…
  • 我不知道任何简单的/罐头。 Zeki 链接到一种方法来判断 toast 表与哪个基表相关联。不过我很好奇……为什么?你想用这个来完成什么?
  • 我的 Rails 项目中有大型 rake 任务,我不想在真空运行时启动。查询需要几个小时才能运行,如果正在运行真空,数据库负载会急剧增加。

标签: postgresql postgresql-9.2 vacuum


【解决方案1】:

这个问题可以通过系统目录轻松解决。我建议加入pg_locks,因为 autovacuum 在它正在处理的表上获得了ShareUpdateExclusiveLock 锁,以避免手动解析来自pg_stat_activity 的查询。

以下查询列出了正在自动清理的表,如果正在清理 toast 表,则解决 pg_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
    );
    

    table 模式是一个 glob 模式,例如 tbl*。在查询结束时重新打开自动清理

    alter table table_name_pattern 
    set (
        autovacuum_enabled = true,
        toast.autovacuum_enabled = true
    );
    

    根据评论进行编辑:

    查询相关表是否正在被清理是不必要且无用的。如果已知一个或多个相关表正在被清理,应该怎么做?等待并继续重复查询,直到没有被清空?并且当没有然后开始长查询只是为了在一段时间后发现自动真空刚刚再次启动?无关紧要。为什么不直接关闭自动真空吸尘器并避免所有麻烦?

    以艰难的方式来做这件事并没有道德上的优势,尤其是在艰难的方式会比简单的方式产生更糟糕的结果时。更简单的代码更易于使用和理解,但不一定更容易构建。很多时候情况正好相反,需要更多的智力努力或准备,而不是复杂的。


    如果 autovacuum 设置在事务中被更改并且该事务被回滚,则设置将恢复到事务开始之前的状态

    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
    

    但是事务内部的设置不会在事务外部看到,所以我猜 autovacuum 仍然会运行。如果这是真的,那么设置必须在事务之外完成并由一个作业控制,无论长时间运行的查询会发生什么,都会将其返回。

    【讨论】:

    • 在某些情况下这是一个有用的答案,所以我赞成它。它实际上并没有像它被问到的那样回答问题,所以我没有给它赏金。
    • @Kirk 它没有按要求回答问题,但它解决了评论中解释的问题。无论如何感谢您的支持。
    • 赏金是为了鼓励某人完成编写“硬”查询的工作。您的回答很有帮助和赞赏,但错过了赏金的重点。也许@Geesu 会接受你的答案,因为它适用于他。
    • @Kirk 编辑注意您的 cmets。
    • “不必要和无用”......这是一个见仁见智的问题。您真的了解所有可能的情况并准备好说没有人可能有您没有考虑过的用例吗?如果这是真的,我建议你去 Ubuntu 论坛并写下“RTFM”和“你不需要那个”回答所有你想要的。这些答案在 SO 上是不合适的。 “没有道德优越感”......这是个人评论和性格假设,在 SO 上也没有地位。
    猜你喜欢
    • 1970-01-01
    • 2011-07-13
    • 1970-01-01
    • 2012-06-25
    • 2018-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多