我找到了一个查询来查看真空吸尘器何时运行,但不是当前正在运行的。(http://heatware.net/databases/postgres-tables-auto-vacuum-analyze/)
是否有查询来完成此操作?我知道我可以点击 pg_stat_activity,但有些真空吸尘器没有表名,而是有 pg_toast.pg_toast_3621837,所以这不会 100% 起作用。
我找到了一个查询来查看真空吸尘器何时运行,但不是当前正在运行的。(http://heatware.net/databases/postgres-tables-auto-vacuum-analyze/)
是否有查询来完成此操作?我知道我可以点击 pg_stat_activity,但有些真空吸尘器没有表名,而是有 pg_toast.pg_toast_3621837,所以这不会 100% 起作用。
这个问题可以通过系统目录轻松解决。我建议加入,pg_locks
因为 autovacuum 会在它正在处理的表上获得ShareUpdateExclusiveLock
锁,以避免手动解析来自pg_stat_activity
.
以下查询列出了正在自动清理的表,如果正在清理 toast 表,则解决 pg_toast 引用,如Postgres pg_toast in autovacuum - which table?@Zeki 链接到的问题。
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_activity
和pg_locks
目录在数据库之间共享,但此查询将仅列出当前数据库中自动清理的表,因为pg_relation
它不是共享目录。
而不是查找表是否正在被清理,而是关闭相关表的自动清理:
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 仍然会运行。如果这是真的,那么设置必须在事务之外完成并由一个作业控制,无论长时间运行的查询会发生什么,都会将其返回。