【问题标题】:Postgres vacuum/demon partially working when issued from JDBC从 JDBC 发出时,Postgres Vacuum/demon 部分工作
【发布时间】:2021-02-24 19:54:51
【问题描述】:

首先,我知道依赖应用层的手动清理很奇怪,但这就是我们决定运行它的方式。 我有以下堆栈:

  1. HikariCP
  2. JDBC
  3. AWS 中的 Postgres 11

现在问题来了。当我们重新开始使用 autovacuum=off 的全新表时,手动真空工作正常。我可以看到 dead_tuples 的数量增长到阈值然后又回到 0。这些表在并行连接中被大量更新(也正在使用 HOT)。在某些时候,死行的数量就像 100k 跳到阈值并回到 100k。 n_dead_tuples 慢慢爬升。

现在最糟糕的是,当您从 pg 控制台发出真空时,所有死元组都被清除,但奇怪的是,当应用程序发出真空时它是成功的,但部分清除了“阈值量记录”,但不是全部? 现在我很确定以下几点:

  • 分析未运行,也未自动清空
  • 没有长时间运行的事务
  • 没有进行复制
  • 这些表是“私有的”

从控制台发出真空与自动提交与 JDBC 有什么区别?为什么从控制台发出的真空正在清理 ALL 元组,而来自 JDBC 的真空只能部分清理它? JDBC 真空是在具有默认隔离级别的池中的新连接中运行的,是的,更新是并行进行的,但这与从控制台执行真空时相同。

来自池的连接是否以某种方式损坏并且看不到更新?隔离是问题吗? 能见度地图损坏? 索引引用旧元组?

旁注:我观察到与 autovacuum on 和成本限制相同的行为,例如 4000-8000 ,阈值默认值 + 5% 。起初 n_dead_tuples 接近 0 大约 4-5 小时......第二天桌子是 86gigs,有数百万死元组。所有其他表都被吸尘并正常...

PS:我会尝试在 JDBC 中记录一个 vac 详细信息。 PS2:因为我们是在 AWS 上运行的,会不会是备份导致它停止清理?

PS3:当提到真空时,我指的是简单真空,而不是完全真空。我们不会发布完全真空。

【问题讨论】:

  • 这听起来不太可能。是的,VACUUM (VERBOSE) 会提供信息。将autovacuum_vacuum_cost_delay = 0 设置为最大速度。
  • 我以前没有做过vaccum,所以我觉得这很有趣。你能显示代码你实际上是如何触发 FULL Vacuum 的吗?还看postgresql.org/docs/current/…,似乎有很多可以尝试的选项。 stackoverflow.com/questions/46982548/…
  • 我没有使用全真空
  • "现在最糟糕的是,当你从 pg 控制台发出真空时,所有死元组都被清除了,但奇怪的是,当应用程序发出真空时它是成功的,但部分清除了“阈值数量记录”,但不是全部?你具体看到了什么让你这么想?
  • @jjanes 虽然一切都已启动并运行,但我可以看到应用程序正在清理,但 n_dead 从 50k-100k 变回 50k...从控制台抽真空,n_dead 下降到 0... .. 过了一会儿,它开始蠕动 10-60,然后从 20-70 回到 20k,依此类推

标签: java postgresql jdbc hikaricp vacuum


【解决方案1】:

主要问题是真空是由另一个用户运行的。我看到的吸尘是 HOT 更新 + 选择在该数据上运行,从而导致页面的动态吸尘。

下一步:清理会受到跨所有模式和表的长时间运行事务的影响。是的,所有模式和表。更改为正确的用户修复了真空,但如果任何其他 schema.table 中有 open_in_transaction,它将被忽略。

工作维护记忆会有所帮助,但最终当系统处于重负载下时,所有吸尘都会暂停。

所以我们稍微升级了数据库的资源,并添加了一个监视器来帮助我们解决问题。

【讨论】:

    猜你喜欢
    • 2013-07-31
    • 2021-07-28
    • 2012-11-07
    • 1970-01-01
    • 2013-10-09
    • 2010-11-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多