<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>长事务 on Zero Day Notes</title>
        <link>https://blog.5772447.xyz/tags/%E9%95%BF%E4%BA%8B%E5%8A%A1/</link>
        <description>Recent content in 长事务 on Zero Day Notes</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh</language>
        <lastBuildDate>Thu, 09 Jul 2026 07:00:00 +0000</lastBuildDate><atom:link href="https://blog.5772447.xyz/tags/%E9%95%BF%E4%BA%8B%E5%8A%A1/index.xml" rel="self" type="application/rss+xml" /><item>
            <title>一次 PostgreSQL 长事务导致表膨胀与 autovacuum 失效、查询性能断崖式下跌的排查实录</title>
            <link>https://blog.5772447.xyz/posts/b1c93f57/</link>
            <pubDate>Thu, 09 Jul 2026 07:00:00 +0000</pubDate>
            <guid>https://blog.5772447.xyz/posts/b1c93f57/</guid>
            <description>&lt;h2 id=&#34;一问题背景&#34;&gt;&lt;a href=&#34;#%e4%b8%80%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;一、问题背景&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;公司内部的工单与结算报表系统后端跑在 PostgreSQL 13（一主两从）上，核心业务表 &lt;code&gt;orders&lt;/code&gt;（订单表）日增约 30 万行。该系统平时表现稳定，单条按主键查询稳定在 2~5ms，分页报表查询也在 200ms 以内。&lt;/p&gt;&#xA;&lt;p&gt;事情发生在一次大促复盘期间。BI 同事反馈，最近两周报表导出的等待时间越来越长，原本跑 10 秒的日报 SQL 现在经常卡到 40 秒以上，且主库磁盘使用率从 55% 悄悄涨到了 81%。由于是从“慢慢变慢”而非“突然宕机”，前几次都被当作临时抖动忽略了，直到某天早高峰一个核心查询超时把接口拖垮，才正式立项排查。&lt;/p&gt;&#xA;&lt;h2 id=&#34;二故障现象&#34;&gt;&lt;a href=&#34;#%e4%ba%8c%e6%95%85%e9%9a%9c%e7%8e%b0%e8%b1%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;二、故障现象&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;现场能观察到的现象有五点，且都指向同一张表：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;查询延迟持续劣化&lt;/strong&gt;：&lt;code&gt;SELECT ... FROM orders WHERE create_time BETWEEN ...&lt;/code&gt; 这类带时间范围扫描的 SQL，执行计划从 Index Scan 退化成 Bitmap Heap Scan 后进一步退化成全表 Seq Scan，耗时从亚秒级爬升到 30~50 秒，且几乎不随业务低峰回落。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;表体积异常膨胀&lt;/strong&gt;：&lt;code&gt;orders&lt;/code&gt; 表逻辑行数约 2100 万，但 &lt;code&gt;pg_relation_size&lt;/code&gt; 显示其堆文件已超过 28GB（按行宽估算正常应约 9GB），物理大小是逻辑数据量的 3 倍多。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;autovacuum 形同虚设&lt;/strong&gt;：&lt;code&gt;pg_stat_user_tables&lt;/code&gt; 里 &lt;code&gt;last_autovacuum&lt;/code&gt; 字段经常停留在几天前，&lt;code&gt;n_dead_tup&lt;/code&gt;（死元组数量）长期维持在千万级且不下降。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;磁盘只增不减&lt;/strong&gt;：主库数据目录每天净增长约 4GB，但业务写入量并没有成比例放大。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;只读从库复制延迟偶发抖动&lt;/strong&gt;：由于主库频繁做重量级清理/检查点，WAL 产生突增，从库 &lt;code&gt;replay_lag&lt;/code&gt; 间歇升高。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;最关键的是：这些现象是&lt;strong&gt;渐进式&lt;/strong&gt;的，单看某一时刻的监控都不算“故障”，组合起来才暴露出性能断崖。&lt;/p&gt;&#xA;&lt;h2 id=&#34;三排查过程&#34;&gt;&lt;a href=&#34;#%e4%b8%89%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;三、排查过程&#xD;&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1-先确认是不是死元组堆积&#34;&gt;&lt;a href=&#34;#1-%e5%85%88%e7%a1%ae%e8%ae%a4%e6%98%af%e4%b8%8d%e6%98%af%e6%ad%bb%e5%85%83%e7%bb%84%e5%a0%86%e7%a7%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;1. 先确认是不是“死元组”堆积&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;PostgreSQL 的 MVCC 机制下，UPDATE/DELETE 不会立刻物理删除旧版本，而是把它们标记为死元组（dead tuple），依赖 autovacuum 回收。先直接看统计：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;8&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; schemaname, relname,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       n_live_tup, n_dead_tup,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       last_vacuum, last_autovacuum,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       round(n_dead_tup::numeric &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;NULLIF&lt;/span&gt;(n_live_tup,&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;AS&lt;/span&gt; dead_pct&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; pg_stat_user_tables&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; n_dead_tup &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;100000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ORDER&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;BY&lt;/span&gt; n_dead_tup &lt;span style=&#34;color:#66d9ef&#34;&gt;DESC&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;LIMIT&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;结果 &lt;code&gt;orders&lt;/code&gt; 表的 &lt;code&gt;n_dead_tup&lt;/code&gt; 高达 4100 万，&lt;code&gt;dead_pct&lt;/code&gt; 接近 195%——也就是死元组比活元组还多一倍。&lt;strong&gt;表已经严重膨胀&lt;/strong&gt;，这与磁盘只增不减的现象完全吻合。&lt;/p&gt;&#xA;&lt;h3 id=&#34;2-为什么-autovacuum-不干活&#34;&gt;&lt;a href=&#34;#2-%e4%b8%ba%e4%bb%80%e4%b9%88-autovacuum-%e4%b8%8d%e5%b9%b2%e6%b4%bb&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;2. 为什么 autovacuum 不干活&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;继续看 autovacuum 的触发条件。&lt;code&gt;pg_stat_user_tables&lt;/code&gt; 里 &lt;code&gt;last_autovacuum&lt;/code&gt; 长期不更新，说明要么没触发，要么触发了但&lt;strong&gt;被阻塞&lt;/strong&gt;。查一个关键指标——最老事务的年龄：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; datname, age(datfrozenxid) &lt;span style=&#34;color:#66d9ef&#34;&gt;AS&lt;/span&gt; xid_age&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; pg_database&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ORDER&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;BY&lt;/span&gt; xid_age &lt;span style=&#34;color:#66d9ef&#34;&gt;DESC&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;主库 &lt;code&gt;xid_age&lt;/code&gt; 已超过 2 亿，逼近 &lt;code&gt;autovacuum_freeze_max_age&lt;/code&gt;（默认 2 亿）。再查是否有长事务卡住：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;8&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; pid, datname, usename, application_name,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#66d9ef&#34;&gt;state&lt;/span&gt;, now() &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; xact_start &lt;span style=&#34;color:#66d9ef&#34;&gt;AS&lt;/span&gt; xact_age,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       now() &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; query_start &lt;span style=&#34;color:#66d9ef&#34;&gt;AS&lt;/span&gt; query_age,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       wait_event_type, wait_event, &lt;span style=&#34;color:#66d9ef&#34;&gt;left&lt;/span&gt;(query, &lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;AS&lt;/span&gt; query&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; pg_stat_activity&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;state&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;IS&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;DISTINCT&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;idle&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;AND&lt;/span&gt; (now() &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; xact_start) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; interval &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;5 minutes&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ORDER&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;BY&lt;/span&gt; xact_age &lt;span style=&#34;color:#66d9ef&#34;&gt;DESC&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;这一查就露馅了：有一个来自 BI 报表服务的连接，&lt;code&gt;state=&#39;idle in transaction&#39;&lt;/code&gt;，&lt;code&gt;xact_age&lt;/code&gt; 已经 26 小时，对应的 &lt;code&gt;query&lt;/code&gt; 是一条 &lt;code&gt;BEGIN&lt;/code&gt; 后没提交也没回滚、只做了一次 &lt;code&gt;SELECT&lt;/code&gt; 的会话。&lt;/p&gt;&#xA;&lt;h3 id=&#34;3-根因链条闭环&#34;&gt;&lt;a href=&#34;#3-%e6%a0%b9%e5%9b%a0%e9%93%be%e6%9d%a1%e9%97%ad%e7%8e%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;3. 根因链条闭环&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;关键点在于：PostgreSQL 的 vacuum &lt;strong&gt;不能回收“被任意活跃事务快照之后产生的死元组”&lt;/strong&gt;。只要有一个事务（哪怕是 idle in transaction）还持有旧快照，它之前版本的所有行对它是“可见”的，vacuum 为了不破坏它的可重复读视图，就只能跳过这些死元组的回收。&lt;/p&gt;&#xA;&lt;p&gt;换句话说：&lt;strong&gt;一个 26 小时没提交的 idle-in-transaction 会话，相当于把整个数据库的死元组回收冻结了 26 小时&lt;/strong&gt;。期间 &lt;code&gt;orders&lt;/code&gt; 表持续被 UPDATE/DELETE，&lt;code&gt;n_dead_tup&lt;/code&gt; 只增不减，autovacuum 即使运行也收效甚微。表越长越大，索引也同步膨胀（index bloat），执行计划因代价估算失真逐渐偏向全表扫描，查询自然断崖式变慢。&lt;/p&gt;&#xA;&lt;p&gt;验证索引膨胀可用 &lt;code&gt;pgstattuple&lt;/code&gt; 扩展：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;CREATE&lt;/span&gt; EXTENSION &lt;span style=&#34;color:#66d9ef&#34;&gt;IF&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;EXISTS&lt;/span&gt; pgstattuple;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; pgstatindex(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;orders_pkey&amp;#39;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- dead_tuple_percent 高达 60%+ 即明显膨胀&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;h3 id=&#34;4-确认阻塞来源&#34;&gt;&lt;a href=&#34;#4-%e7%a1%ae%e8%ae%a4%e9%98%bb%e5%a1%9e%e6%9d%a5%e6%ba%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;4. 确认阻塞来源&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;用锁视图确认 vacuum 进程是否因该长事务被挡：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; a.pid, a.usename, a.&lt;span style=&#34;color:#66d9ef&#34;&gt;state&lt;/span&gt;, l.locktype, l.&lt;span style=&#34;color:#66d9ef&#34;&gt;mode&lt;/span&gt;, l.&lt;span style=&#34;color:#66d9ef&#34;&gt;granted&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       b.query &lt;span style=&#34;color:#66d9ef&#34;&gt;AS&lt;/span&gt; blocking_query&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; pg_locks l&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;JOIN&lt;/span&gt; pg_stat_activity a &lt;span style=&#34;color:#66d9ef&#34;&gt;ON&lt;/span&gt; a.pid &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; l.pid&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;LEFT&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;JOIN&lt;/span&gt; pg_locks bl &lt;span style=&#34;color:#66d9ef&#34;&gt;ON&lt;/span&gt; bl.locktype &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; l.locktype &lt;span style=&#34;color:#66d9ef&#34;&gt;AND&lt;/span&gt; bl.objid &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; l.objid &lt;span style=&#34;color:#66d9ef&#34;&gt;AND&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;NOT&lt;/span&gt; bl.&lt;span style=&#34;color:#66d9ef&#34;&gt;granted&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; l.&lt;span style=&#34;color:#66d9ef&#34;&gt;granted&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;结果印证：autovacuum worker 在 &lt;code&gt;orders&lt;/code&gt; 上请求 &lt;code&gt;ShareUpdateExclusiveLock&lt;/code&gt; 处于 &lt;code&gt;granted=false&lt;/code&gt; 等待状态，阻塞者正是那个 26 小时的长事务会话。链条完全闭合。&lt;/p&gt;&#xA;&lt;h2 id=&#34;四解决方案&#34;&gt;&lt;a href=&#34;#%e5%9b%9b%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;四、解决方案&#xD;&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1-立即释放冻结的长事务&#34;&gt;&lt;a href=&#34;#1-%e7%ab%8b%e5%8d%b3%e9%87%8a%e6%94%be%e5%86%bb%e7%bb%93%e7%9a%84%e9%95%bf%e4%ba%8b%e5%8a%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;1. 立即释放“冻结”的长事务&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;先与 BI 团队确认该会话已无业务用途，强制终止以解冻 vacuum：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- 先尝试优雅通知（应用侧回滚），无效则：&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; pg_terminate_backend(&lt;span style=&#34;color:#ae81ff&#34;&gt;12345&lt;/span&gt;);  &lt;span style=&#34;color:#75715e&#34;&gt;-- 12345 为 above 查到的 pid&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;会话断开后，立马手动触发一次对 &lt;code&gt;orders&lt;/code&gt; 的 vacuum：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;VACUUM&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;VERBOSE&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;ANALYZE&lt;/span&gt;) orders;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;⚠️ 注意：&lt;strong&gt;不要用 &lt;code&gt;VACUUM FULL&lt;/code&gt; 作为首选&lt;/strong&gt;。&lt;code&gt;VACUUM FULL&lt;/code&gt; 会持排他锁重写整张表，在大表上会长时间锁表影响业务。真正需要回收物理空间时，更优解是使用 &lt;code&gt;pg_repack&lt;/code&gt;（在线重组，只短暂加锁）。&lt;/p&gt;&#xA;&lt;h3 id=&#34;2-在线重组回收膨胀空间&#34;&gt;&lt;a href=&#34;#2-%e5%9c%a8%e7%ba%bf%e9%87%8d%e7%bb%84%e5%9b%9e%e6%94%b6%e8%86%a8%e8%83%80%e7%a9%ba%e9%97%b4&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;2. 在线重组回收膨胀空间&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;安装并使用 &lt;code&gt;pg_repack&lt;/code&gt; 对 &lt;code&gt;orders&lt;/code&gt; 做在线瘦身：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pg_repack -d bizdb -t public.orders --no-order&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;执行后 &lt;code&gt;orders&lt;/code&gt; 堆文件从 28GB 回落到约 9.5GB，索引 &lt;code&gt;dead_tuple_percent&lt;/code&gt; 从 60% 降到 2%，报表查询耗时回到 1 秒以内。&lt;/p&gt;&#xA;&lt;h3 id=&#34;3-紧急调优-autovacuum-阈值&#34;&gt;&lt;a href=&#34;#3-%e7%b4%a7%e6%80%a5%e8%b0%83%e4%bc%98-autovacuum-%e9%98%88%e5%80%bc&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;3. 紧急调优 autovacuum 阈值&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;对写入频繁的大表降低触发门槛，让 vacuum 更积极：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ALTER&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;TABLE&lt;/span&gt; orders &lt;span style=&#34;color:#66d9ef&#34;&gt;SET&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  autovacuum_vacuum_scale_factor &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;02&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  autovacuum_vacuum_threshold    &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;5000&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  autovacuum_analyze_scale_factor &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;05&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;h3 id=&#34;4-设置事务超时兜底&#34;&gt;&lt;a href=&#34;#4-%e8%ae%be%e7%bd%ae%e4%ba%8b%e5%8a%a1%e8%b6%85%e6%97%b6%e5%85%9c%e5%ba%95&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;4. 设置事务超时兜底&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;在数据库级别给“空闲在事务中”的会话加超时，从机制上杜绝此类问题复发：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ALTER&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;DATABASE&lt;/span&gt; bizdb &lt;span style=&#34;color:#66d9ef&#34;&gt;SET&lt;/span&gt; idle_in_transaction_session_timeout &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;5min&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;同时在应用连接池（PgBouncer）层面设置 &lt;code&gt;server_idle_timeout&lt;/code&gt; 和 &lt;code&gt;query_timeout&lt;/code&gt;，双保险。&lt;/p&gt;&#xA;&lt;h2 id=&#34;五根因分析&#34;&gt;&lt;a href=&#34;#%e4%ba%94%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;五、根因分析&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;本质是一条“不起眼”的 BI 会话泄漏：&lt;code&gt;BEGIN&lt;/code&gt; 后查询完毕却忘记 &lt;code&gt;COMMIT/ROLLBACK&lt;/code&gt;，连接被连接池保活成 &lt;code&gt;idle in transaction&lt;/code&gt;。在 MVCC 下，这个未结束事务持有的旧快照，使 vacuum 无法回收该快照之后产生的任何死元组。叠加 &lt;code&gt;orders&lt;/code&gt; 表高频 UPDATE/DELETE，死元组以千万级速度累积，表与索引持续膨胀，执行计划劣化，最终表现为查询性能断崖式下跌。问题不在 autovacuum 配置（默认配置对大多数表是够的），而在&lt;strong&gt;一个长事务把整个回收链路“冻住”了&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;h2 id=&#34;六预防措施&#34;&gt;&lt;a href=&#34;#%e5%85%ad%e9%a2%84%e9%98%b2%e6%8e%aa%e6%96%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;六、预防措施&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;集群级设置超时阈值&lt;/strong&gt;：&lt;code&gt;idle_in_transaction_session_timeout&lt;/code&gt;、&lt;code&gt;statement_timeout&lt;/code&gt;、&lt;code&gt;lock_timeout&lt;/code&gt; 三件套在实例/库级别统一配置，避免单个泄漏会话拖垮全局。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;监控“长事务”而非只监控慢 SQL&lt;/strong&gt;：把 &lt;code&gt;pg_stat_activity&lt;/code&gt; 中 &lt;code&gt;state=&#39;idle in transaction&#39;&lt;/code&gt; 且 &lt;code&gt;now()-xact_start &amp;gt; 5min&lt;/code&gt; 的会话接入告警，做到分钟级发现。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;监控表膨胀率&lt;/strong&gt;：定期跑 bloat 估算 SQL，对 &lt;code&gt;dead_pct &amp;gt; 50%&lt;/code&gt; 的表自动派单处理；对大表常态化 &lt;code&gt;pg_repack&lt;/code&gt; 维护窗口。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;应用侧规范事务&lt;/strong&gt;：禁止“查询后不提交”的写法，所有事务显式 &lt;code&gt;COMMIT/ROLLBACK&lt;/code&gt;；BI/报表类长查询改用独立只读从库 + &lt;code&gt;SET transaction_read_only&lt;/code&gt;，与核心写入库隔离。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;autovacuum 大表定制&lt;/strong&gt;：对写入频繁的大表单独下调 &lt;code&gt;scale_factor&lt;/code&gt;、上调 &lt;code&gt;cost_limit&lt;/code&gt;，避免默认参数在大表上响应过慢。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;七总结&#34;&gt;&lt;a href=&#34;#%e4%b8%83%e6%80%bb%e7%bb%93&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;七、总结&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;这次故障的典型之处在于：它&lt;strong&gt;没有报错、没有宕机、没有硬件异常&lt;/strong&gt;，纯粹是“一个被遗忘的事务”通过 MVCC 机制缓慢冻结了整个回收链路，最终以“查询变慢”的形式爆发。给运维的启示是——监控不能只看 CPU/内存/慢日志，事务年龄（&lt;code&gt;age(datfrozenxid)&lt;/code&gt;）和 &lt;code&gt;idle in transaction&lt;/code&gt; 长会话同样是高优先级的“沉默杀手”。配好超时阈值 + 盯住长事务 + 定期治理表膨胀，基本能把这类问题挡在发生之前。&lt;/p&gt;&#xA;</description>
        </item></channel>
</rss>
