如何对 Aurora PostgreSQL 兼容版中的事务 ID 回卷问题进行故障排除?
我想对 Amazon Aurora PostgreSQL 兼容版数据库 (DB) 集群中的事务 ID 回卷问题进行故障排除。
解决方法
监控指标和 CloudWatch 警报以防止出现问题
要监控最久未进行 vacuum 的事务年龄,请查看 Amazon CloudWatch 中的 MaximumUsedTransactionIDs 指标。为防止事务 ID 回卷问题,请创建 CloudWatch 警报。有关更多信息,请参阅在 Amazon Relational Database Service (Amazon RDS) for PostgreSQL 中实施事务 ID 回卷预警系统。
运行诊断查询
使用 psql 或 pgAdmin 连接到 PostgreSQL 数据库实例。
要检查数据库年龄,请运行以下命令:
SELECT datname, age(datfrozenxid) FROM pg_database ORDER BY 2 DESC LIMIT 20;
**注意:**如果输出显示 rdsadmin 或 template0 数据库的事务 ID 年龄最大,请联系 AWS Support。
要连接到年龄最高的数据库以识别表的潜在问题,请运行以下命令:
SELECT c.relnamespace::regnamespace as schema_name, c.oid::regclass as table_name, greatest(age(c.relfrozenxid),age(t.relfrozenxid)) as age, pg_size_pretty(pg_table_size(c.oid)) as table_size, t.relkind, t.relpersistence FROM pg_class c LEFT JOIN pg_class t ON c.reltoastrelid = t.oid WHERE c.relkind IN ('r', 'm') ORDER BY 3 DESC LIMIT 20;
要查看年龄值较高的表的 autovacuum 历史记录,请运行以下命令:
SELECT relname, n_live_tup, n_tup_upd, n_tup_del, n_dead_tup, last_vacuum, last_autovacuum, last_analyze, last_autoanalyze FROM pg_stat_user_tables WHERE relname='table_name';
**注意:**请将 table_name 替换为您的表名。
要监控活动的 vacuum 操作,请运行以下命令:
SELECT datname, usename, pid, state, wait_event, current_timestamp - xact_start AS xact_runtime, query FROM pg_stat_activity WHERE upper(query) LIKE '%VACUUM%' AND pid <> pg_backend_pid() ORDER BY xact_start;
解决 autovacuum 进程阻塞问题
如果您使用以下 Aurora PostgreSQL 兼容版本之一,请参阅识别并解决 Aurora PostgreSQL 中的激进 vacuum 阻塞问题:
- 13.19 或更高版本
- 14.16 或更高版本
- 15.11 或更高版本
- 16.7 或更高版本
- 17.2 或更高版本
解决长时间运行的事务
长时间运行的事务或空闲的事务内会话可能会阻塞 autovacuum。
您会在 PostgreSQL 错误日志中看到以下警告消息:
"WARNING: oldest xmin is far in the past HINT: Close open transactions soon to avoid wraparound problems."
要识别阻塞 autovacuum 的事务,请运行以下命令:
SELECT pid, age(backend_xid), substr(query,1,20), extract(epoch from now()) - extract(epoch from xact_start) as duration, state FROM pg_stat_activity WHERE xact_start is not null AND age(backend_xid) is not null ORDER BY 2 DESC LIMIT 10;
要解决此问题,您可以取消活动查询或终止连接。
要取消活动查询,请运行以下命令:
SELECT pg_cancel_backend(pid);
**注意:**请将 pid 替换为查询结果中的进程 ID。
要终止连接,请运行以下命令:
SELECT pg_terminate_backend(pid);
**注意:**请将 pid 替换为查询结果中的进程 ID。
要确保长时间运行的事务不会再次阻塞 autovacuum,请设置 statement_timeout、idle_in_transaction_session_timeout 和 log_min_duration_statement 参数。
解决非活动逻辑复制槽问题
要识别非活动的槽,请运行以下命令:
SELECT slot_name, slot_type, database, xmin, catalog_xmin, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(),restart_lsn)) AS replicationSlotLag, active FROM pg_replication_slots ORDER BY age(xmin), age(catalog_xmin) DESC;
**警告:**在删除复制槽之前,请确认其没有正在进行的复制、处于非活动状态且无法恢复。如果您删除了仍在复制、处于活动状态且可恢复的复制槽,则可能会中断复制或导致数据丢失。
要删除未使用的槽,请运行以下命令:
SELECT pg_drop_replication_slot('slot_name');
**注意:**请将 slot_name 替换为您的复制槽名称。
解决读取器实例问题
要识别 Aurora 集群中可能阻碍热备用反馈并阻塞 autovacuum 的读取器,请运行以下查询:
select server_id, feedback_epoch, feedback_xmin from aurora_replica_status() WHERE (feedback_xmin IS NOT NULL AND feedback_xmin > 0)
对于全局数据库集群中阻碍热备用反馈的读取器,请运行以下查询:
select server_id,aws_region,feedback_epoch,feedback_xmin from aurora_global_db_instance_status () WHERE (feedback_xmin IS NOT NULL AND feedback_xmin > 0);
在 feedback_epoch 和 feedback_xmin 组合值最低的读取器实例中运行以下查询:
SELECT pid, age(backend_xid), substr(query,1,20), extract(epoch from now()) - extract(epoch from xact_start) as duration, state FROM pg_stat_activity WHERE backend_xmin::text::bigint =feedback_xmin
**注意:**请将 feedback_xmin 替换为上述查询结果中的 feedback_xmin 值。
如果可以安全操作,请使用 pg_terminate_backend(pid) 终止长时间运行的事务。
解决未提交的已准备事务
要识别已准备事务,请运行以下命令:
SELECT database, gid, prepared, owner, database, transaction::text::bigint as xid, now() - prepared AS time_since_prepared FROM pg_prepared_xacts ORDER BY age(transaction) DESC;
要解决已准备事务,您可以提交或回滚已准备事务。
要提交已准备事务,请运行以下命令:
COMMIT PREPARED 'gid'
**注意:**请将 gid 替换为查询结果中的全局事务 ID。
**警告:**在回滚已准备事务之前,请确保该事务不属于某个分布式事务序列。
要回滚已准备事务,请运行以下命令:
ROLLBACK PREPARED 'gid'
**注意:**请将 gid 替换为查询结果中的全局事务 ID。
解决孤立的临时表问题
当 PostgreSQL 的 autovacuum 进程遇到孤立的临时表时,会记录以下事件:
LOG: autovacuum: found orphan temp table "%s"."%s" in database "%s"
要识别孤立的临时表,请运行以下命令:
SELECT oid, relname, relnamespace::regnamespace, age(relfrozenxid) FROM pg_class WHERE relpersistence = 't' ORDER BY age(relfrozenxid) DESC;
要删除临时表,请运行以下命令:
DROP TABLE temporary_table
**注意:**请将 temporary_table 替换为您的临时表名称。
解决 vacuum 性能问题
当 autovacuum 运行缓慢时,冻结操作可能会延迟。
要解决此问题,首先增加 autovacuum_max_workers 参数以支持更多并发 vacuum 操作。然后,使用以下公式等量增加 autovacuum_vacuum_cost_limit 参数:
Individual worker's cost_limit = autovacuum_vacuum_cost_limit / autovacuum_max_workers
如果在增加参数后 vacuum 性能仍然不足,请将您的 Amazon RDS 实例升级到具有更多 vCPU 的实例类。您可以在表级别修改 autovacuum_vacuum_cost_delay 参数以加快 autovacuum 操作。
要在表级别修改 autovacuum_vacuum_cost_delay 参数,请运行以下命令:
ALTER TABLE mytable SET ( autovacuum_vacuum_cost_delay = value, autovacuum_vacuum_cost_limit = value );
**注意:**请将 mytable 替换为您的表名,并将 value 替换为所需的参数值。
大型索引的 vacuum 性能
在对大型索引执行 vacuum 操作时,内存限制会强制对同一索引进行多次扫描,从而显著增加 VACUUM 的总持续时间。
如果您在 PostgreSQL 16 或更早版本中遇到大型索引上 VACUUM 操作缓慢的情况,请检查以下潜在原因:
- 索引大小超过 1GB。
- 发生多次 VACUUM 扫描。要查看扫描次数,请查询 pg_stat_progress_vacuum 视图中的 index_vacuum_count。
- maintenance_work_mem 或 autovacuum_work_mem 配置有误。
要解决此问题,请执行以下操作:
- 删除未使用或重复的索引。
- 增加 maintenance_work_mem 或 autovacuum_work_mem。要使新的内存设置生效,请终止当前正在运行 autovacuum 的进程
- 手动执行 VACUUM FREEZE 操作,并在会话中增加 maintenance_work_mem。
如果您使用的是 PostgreSQL 12 或更高版本,请运行以下命令,查看可能跳过索引清理的手动 vacuum 操作:
VACUUM (INDEX_CLEANUP FALSE, VERBOSE TRUE) table_name;
**注意:**请将 table_name 替换为您的表名。
逻辑不一致
如果逻辑不一致的索引阻塞了 autovacuum 进程,您可能会收到以下错误消息之一:
- ERROR: right sibling's left-link doesn't match:block 5 links to 10 instead of expected 2 in index ix_name
- ERROR: failed to re-find parent key in index "XXXXXXXXXX" for deletion target page XXX CONTEXT: while vacuuming index index_name of relation schema.table
要解决此问题,请重建索引。对于 PostgreSQL 12 及更高版本,您也可以跳过索引清理。
要重建索引,请运行以下命令:
REINDEX INDEX ix_name CONCURRENTLY;
**注意:**请将 ix_name 替换为您的索引名称。
-or-
对于 PostgreSQL 12 及更高版本,如需跳过索引清理,请运行以下命令:
VACUUM FREEZE INDEX_CLEANUP FALSE table_name;
**注意:**请将 table_name 替换为您的表名。
相关信息
PostgreSQL 网站上的 Preventing transaction ID wraparound failures(防止事务 ID 回卷失败)
在 Amazon Aurora PostgreSQL 上使用 PostgreSQL autovacuum
了解 Amazon RDS for PostgreSQL 环境中的 autovacuum
如何结束我的 Amazon RDS for PostrgreSQL 或 Aurora PostgreSQL 兼容版数据库实例中长时间运行的查询?
