postgresql - 为什么写在一个表中会阻止另一个表中的真空?

标签 postgresql vacuum autovacuum

具有 READ COMMITTED 隔离级别,已执行写操作的空闲事务将防止 vacuum 清理事务写入的表的死行。

对于由仍在进行中的事务写入的表来说,这一点很明显。 Here你可以找到一个很好的解释。

但我不清楚为什么此限制也会影响任何其他表。

例如:事务 T 启动并更新表 B,当 T 处于“idle in transaction”状态时,对表 A 执行 vacuum。在这种场景下,为什么A中的死行无法去除?

这是我做的:

# show default_transaction_isolation;
 default_transaction_isolation 
-------------------------------
 read committed
(1 row)
# create table a (v int);
CREATE TABLE
# create table b (v int);
CREATE TABLE

# insert into a values (generate_series(1,1000));
INSERT 0 1000

此时我进行更新以生成新的 1000 个死行

# update a set v = v + 1;
UPDATE 1000

Vacuuming 将按预期删除它们:

# vacuum verbose a;
INFO:  vacuuming "public.a"
INFO:  "a": removed 1000 row versions in 5 pages
INFO:  "a": found 1000 removable, 1000 nonremovable row versions in 9 out of 9 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 0 unused item pointers.
0 pages are entirely empty.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
VACUUM

我现在开始在表 b 中写入事务 T:

# begin;
BEGIN
# insert into b values (generate_series(1,1000));
INSERT 0 1000

我在 T 之后开始的不同事务 T1 中再次生成更多死行:

# begin;
# update a set v = v + 1;
# commit;

不同的事务中:

# vacuum verbose a;
INFO:  vacuuming "public.a"
INFO:  "a": found 0 removable, 2000 nonremovable row versions in 9 out of 9 pages
DETAIL:  1000 dead row versions cannot be removed yet.
There were 34 unused item pointers.
0 pages are entirely empty.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
VACUUM

这是相关部分:详细信息:1000 个死行版本尚无法删除。

如果我提交事务 T 并再次执行 vacuum,我会按预期删除死行:

# vacuum verbose a;
INFO:  vacuuming "public.a"
INFO:  "a": removed 1000 row versions in 5 pages
INFO:  "a": found 1000 removable, 1000 nonremovable row versions in 9 out of 9 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 34 unused item pointers.
0 pages are entirely empty.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
VACUUM

最佳答案

通过 Twitter 跟进这个问题.

当前(至少达到 PostgreSQL 9.6)行为是:

任何 表中执行写入操作的实时事务将防止清除由任何其他表 中第一个实时事务之后开始的已提交事务生成的死行。

从概念的角度来看,即使这个限制也不是必需的,它是当前算法实现的方式,以提高检查死行原因的性能。

关于postgresql - 为什么写在一个表中会阻止另一个表中的真空?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46099743/

相关文章:

php - 如何使数组的输出不同?

sql - 如何将数据插入到其他列中没有 NULL 的特定列中?

postgresql - 我怎么知道 Postgres 表的统计信息是否是最新的?

postgresql - Postgres Vacuum 不释放空间

python - 使用 Python 连接到 Amazon RDS Postgresql 数据库时出错

postgresql - 不能使用 UUID 作为主键:Uuid:diesel::Expression 不满足

sqlite 增量真空仅删除一个空闲页面

postgresql - 大表的 Autovacuum 花费的时间太长

PostgreSQL 索引膨胀率大于表膨胀率和 autovacuum_vacuum_scale_factor

database - 在 RDS 实例上收缩 pg_toast