6

在创建/删除/更新查询时出现错误:

错误:数据库不接受命令以避免数据库“mydb”中的环绕数据丢失提示:停止 postmaster 并使用独立后端清理该数据库。您可能还需要提交或回滚旧的准备好的事务。

因此,数据库被阻塞,只能执行 SELECT 查询。

数据库大小 350 GB。1 个表(my_table)有约 10 亿行。

系统:“x86_64-unknown-linux-gnu 上的 PostgreSQL 9.3.4,由 gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-4) 编译,64 位”

postgresq.conf 一些设置:

effective_io_concurrency = 15           # 1-1000; 0 disables prefetching
autovacuum_vacuum_cost_delay = -1

#vacuum_cost_delay = 0                  # 0-100 milliseconds
#vacuum_cost_page_hit = 1               # 0-10000 credits
#vacuum_cost_page_miss = 10             # 0-10000 credits
#vacuum_cost_page_dirty = 20            # 0-10000 credits
#vacuum_cost_limit = 200 

我不使用准备好的交易。但是每天使用基本存储过程(这意味着自动交易,对吗?)5000 万次。

目前,“autovacuum: VACUUM ANALYZE public.my_table ( to prevent wraparound)”正在执行,该查询活动几乎持续了 12 个小时。

据我了解,未抽空的死人的问题,对吧?

如何解决这个问题并在未来防止这种情况发生?请帮忙 :)

故事结束(~一个月后) 现在我的大桌子被数千张桌子隔开。每个小桌子的吸尘速度都要快得多。Autovacuum 配置设置为更接近默认值。如果需要,我可以再次设置为更具侵略性,但到目前为止,拥有数十亿行的数据库运行良好。

所以,题目的问题应该不会再出现了。

ps 现在我将 Postgres-XL 视为数据可扩展性的下一步。

4

2 回答 2

9

问题不是死元组,而是控制行可见性的事务 ID。每个事务都有一个连续的 XID,因为它们是 32 位整数,它们最终会回绕。

有关更多详细信息,请参见此处:http ://www.postgresql.org/docs/9.3/static/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND ,但简短的版本是需要VACUUM编辑所有表(手动或使用 autovacuum)至少每 20 亿次交易。不吸尘的时间越长,它需要的时间就越长。

要解决您当前的问题,您不需要执行 a VACUUM ANALYZE,只需执行VACUUM- 我不确定速度差异有多大,但应该更快。

这运行在什么样的硬件上,你的maintenance_work_mem设置是什么?您可能想要提升它(可能是暂时的)以更快地完成 VACUUM。

将来,您基本上只需要更多 VACUUM:要么增加 autovacuum 频率(例如,请参见此处:https : //dba.stackexchange.com/questions/21068/aggressive-autovacuum-on-postgresql),甚至安排手动 VACUUM与 cron。还要看vacuum_freeze_min_age和相关的设置。

它是什么样的数据,你正在运行什么样的事务?那是一个很大的表,它可以分区(例如按日期)吗?

编辑

您可能还想启用log_autovacuum_min_duration(将其设置为一个较小的值),以查看当数据库处于活动状态时 autovacuum 实际在做什么,以及是否存在阻止其运行的锁定问题。

回复评论

您不必单独运行,您现在VACUUM可以运行它,除非这会过多地干扰您的其他数据库。只需以超级用户身份进行操作,系统表也会被清空。

进行转储/恢复似乎很激烈,我无法想象它会比完成 VACUUM 更快。

离开存储过程将无济于事:任何修改数据的查询都会生成 XID,如果显式使用事务并不重要,它们仍然是事务。

你走对了——让 autovacuum 跟上你的插入/更新是最好的解决方案(记录它的活动应该有助于了解现在出了什么问题)。

从您的表结构来看,这可能是表分区的经典案例(http://www.postgresql.org/docs/9.3/static/ddl-partitioning.html) - 我认为这都是插入,而不是比更新/删除?如果您总是写入一个小分区,则可以更积极地清理它(可以为每个表配置自动清理),并 VACUUM FREEZE 其他分区。

于 2014-05-01T08:49:19.170 回答
0

我认为您别无选择,只能停止数据库,以独立模式重新启动,然后进行清理。让 autovac 完成将无济于事,因为一旦完成,它将去更新系统目录以反映该完成,并且该更新将被拒绝,因为它无法获取所需的事务 ID。至少那是我的经验。

至于以后防止它,您是否定期重新启动数据库?如果您每 24 小时重新启动一次数据库,但您有一个需要 30 小时清理的表,那么该表将永远无法成功清理,最终您会遇到麻烦。

于 2014-05-01T15:54:29.840 回答