database - Postgresql:数据库不接受命令以避免环绕数据丢失

标签 database postgresql rdbms vacuum

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

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 亿个事务都需要 VACUUMed(手动或使用 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/

相关文章:

database - 使用用户定义的类型作为主键

postgresql - 表之间有唯一约束

postgresql - postgresql 中的 Liquibase 不区分大小写

mysql - 当我尝试在多对多关联表上设置 2 个外键时,为什么会收到此错误消息? "Foreign key constraint is incorrectly formed"

database - Excel 可以将自己用作数据库吗?

multithreading - 多线程 DBMS?

sql - 可能的黑客攻击尝试。如何判断我的数据库是否已被泄露

database - 重新安装脚本会清除我已填充的数据库

python - Django IntegrityError 列 "author_id"中的 null 值违反了非空约束

postgresql - 在一个表中删除级联