在创建/删除/更新查询时出现错误:
ERROR: database is not accepting commands to avoid wraparound data loss in database "mydb" HINT: Stop the postmaster and use a standalone backend to vacuum that database. You might also need to commit or roll back old prepared transactions.
因此,数据库被阻塞,只能执行 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 万次。
Сurrently "autovacuum: VACUUM ANALYZE public.my_table (to prevent wraparound)"正在执行,该查询事件将近 12 小时。
据我所知,问题是未抽空的死元组,对吗?
如何解决这个问题并防止将来发生这种情况?请帮助:)
故事的结尾(~一个月后) 现在我的大表被数千个表分区。每张小 table 的吸尘速度都快得多。 Autovacuum 配置设置得更接近默认值。如果需要,我可以再次设置为更激进,但到目前为止,拥有数十亿行的数据库运行良好。
所以,题主的问题应该不会再出现了。
现在我正在将 Postgres-XL 视为数据可扩展性的下一步。
最佳答案
问题不在于死元组,而在于控制行可见性的事务 ID。每个事务都有一个连续的 XID,因为它们是 32 位整数,它们最终会回绕。
查看此处了解更多详情:http://www.postgresql.org/docs/9.3/static/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND ,但简短的版本是所有表至少每 20 亿个事务都需要 VACUUM
ed(手动或使用 autovacuum)。不吸尘的时间越长,所需的时间就越长。
要解决您当前的问题,您不需要执行 VACUUM ANALYZE
,只需执行 VACUUM
- 我不确定速度差异有多大,但它应该更快。
这运行在什么样的硬件上,你的 maintenance_work_mem
设置了什么?您可能想要提高它(可能是暂时的)以更快地完成 VACUUM。
在未来,你基本上只需要更多的 VACUUM:要么增加 autovacuum 频率(例如,参见此处:https://dba.stackexchange.com/questions/21068/aggressive-autovacuum-on-postgresql),要么甚至使用 cron 安排手动 VACUUM。另请查看 vacuum_freeze_min_age
和相关设置。
它是什么类型的数据,您运行的是什么类型的交易?这是一个很大的表,它可以分区吗(例如,按日期)?
编辑
您可能还想启用 log_autovacuum_min_duration
(将其设置为较小的值),以查看当数据库处于事件状态时 autovacuum 实际在做什么,以及是否存在阻止其运行的锁定问题。
回应评论
您必须独立运行VACUUM
,您现在可以运行它,除非这会对您的其他数据库产生过多干扰。只需要以 super 用户身份执行,因此系统表也会被清空。
转储/恢复似乎很激烈,我无法想象它会比完成 VACUUM 更快。
远离存储过程不会有帮助:任何修改数据的查询都会生成 XID,如果您明确使用事务并不重要,它们仍然是事务。
您的方法是正确的 - 让 autovacuum 跟上您的插入/更新是最好的解决方案(记录其事件应该有助于了解现在出了什么问题)。
从您的表结构来看,这可能是表分区的经典案例 ( http://www.postgresql.org/docs/9.3/static/ddl-partitioning.html ) - 我认为这都是插入而不是更新/删除是对的吗?如果您总是写入一个小分区,则可以更积极地清理它(可以为每个表配置 autovacuum),然后对其他分区进行 VACUUM FREEZE。
关于database - Postgresql:数据库不接受命令以避免环绕数据丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23404235/