
是的,你没看错。空闲事务可能导致大量表膨胀,而清理过程可能无法解决这一问题。膨胀会导致性能下降,并可能通过死元组不断侵占磁盘空间。
本博客深入探讨了空闲事务如何导致表膨胀、为什么这会带来问题以及避免这种情况的实用策略。
当未使用或过时的数据(称为死元组)在表和索引中累积时,PostgreSQL 中的表就会膨胀。PostgreSQL 使用多版本并发控制 (MVCC)机制来维护数据一致性。每次更新或删除都会创建一行的新版本,而旧版本则会保留,直到通过自动清理过程或手动清理将其清理干净。
当这些死元组堆积起来且未被移除时,膨胀就会成为问题,从而增加表和索引的大小。表越大,查询速度越慢,导致数据库性能下降和存储成本增加。
PostgreSQL 中的空闲事务是连接到数据库但未主动发出查询的会话。空闲事务有两种主要状态:
Autovacuum 是 PostgreSQL 进程,负责清理死元组并回收空间。但是,autovacuum 无法移除对打开的事务仍然可见的死元组。当事务处于“事务中空闲”状态时,它会保留数据库的快照,防止删除可能仍需要访问的行。
例如:
长时间存在的空闲事务会加剧问题。这些事务会持有锁或快照,从而阻止自动清理或手动VACUUM操作等清理过程。这会产生连锁反应:
空闲事务除了会导致表膨胀之外,还会导致一系列问题:
幸运的是,通过主动监控、配置和应用程序设计,可以避免闲置交易和由此导致的膨胀。以下是一些策略:
第一步是识别空闲或处于事务空闲状态的会话。使用以下查询查找延迟的事务:
SELECT
pid,
usename AS username,
state,
state_change,
query
FROM
pg_stat_activity
WHERE
state IN ('idle', 'idle in transaction');
使用此信息来识别长时间运行的空闲会话并采取纠正措施。
PostgreSQL 提供了idle_in_transaction_session_timeout参数来自动终止空闲时间过长的事务。这可以防止长时间运行的空闲事务持有锁和快照。
在postgresql.conf中全局设置此参数:
idle_in_transaction_session_timeout = '5min'
或者将其应用于特定角色或数据库:
ALTER ROLE my_user SET idle_in_transaction_session_timeout = '5min'; ALTER DATABASE my_database SET idle_in_transaction_session_timeout = '5min';
当达到此超时时,PostgreSQL 会自动终止空闲事务并出现错误。
使用PgBouncer或Pgpool-II等连接池来管理和限制与数据库的连接数。连接池可确保:
大多数空闲事务都是由不良的应用程序设计引起的。请确保您的应用程序:
虽然空闲事务会阻止自动清理,但调整自动清理参数可确保更积极地触发清理。请考虑以下调整:
ALTER TABLE my_table SET ( autovacuum_vacuum_threshold = 50, autovacuum_vacuum_scale_factor = 0.1 );
利用 PostgreSQL 监控视图(例如pg_stat_activity 、pg_stat_user_tables)或第三方工具(例如pgAdmin或pgBadger)来跟踪空闲事务和表随时间的膨胀。
如果需要,您可以手动终止阻止关键操作的空闲事务。使用以下查询终止空闲事务:
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state = 'idle in transaction' AND state_change < NOW() - INTERVAL '10 minutes';
空闲事务乍一看似乎无害,但它们可能会导致表膨胀、阻塞维护任务和不必要地消耗资源,从而悄悄导致严重的性能问题。通过监控、超时和应用程序优化主动管理空闲事务对于维护高性能 PostgreSQL 数据库至关重要。
通过采用这些最佳实践,您可以防止空闲事务对数据库造成严重破坏,并确保系统干净、高效且可扩展。不要让空闲事务成为 PostgreSQL 性能的隐形杀手 - 立即采取行动,保持数据库健康且高效。
#PG证书#PG考试#PostgreSQL培训#PostgreSQL考试#PostgreSQL认证
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69998444/viewspace-3069628/ ,如需转载,请注明出处,否则将追究法律责任。