<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>PostgreSQL案例 on 最后的DBA</title><link>https://lastdba.com/categories/postgresql%E6%A1%88%E4%BE%8B/</link><description>Recent content in PostgreSQL案例 on 最后的DBA</description><generator>Hugo -- gohugo.io</generator><language>zh-CN</language><copyright>© 2026 liuzhilong62</copyright><lastBuildDate>Mon, 09 Mar 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://lastdba.com/categories/postgresql%E6%A1%88%E4%BE%8B/index.xml" rel="self" type="application/rss+xml"/><item><title>案例-起库失败和sysv共享内存</title><link>https://lastdba.com/2026/03/09/%E6%A1%88%E4%BE%8B-%E8%B5%B7%E5%BA%93%E5%A4%B1%E8%B4%A5%E5%92%8Csysv%E5%85%B1%E4%BA%AB%E5%86%85%E5%AD%98/</link><pubDate>Mon, 09 Mar 2026 00:00:00 +0000</pubDate><guid>https://lastdba.com/2026/03/09/%E6%A1%88%E4%BE%8B-%E8%B5%B7%E5%BA%93%E5%A4%B1%E8%B4%A5%E5%92%8Csysv%E5%85%B1%E4%BA%AB%E5%86%85%E5%AD%98/</guid><description>&lt;h2 class="relative group"&gt;问题现象
 &lt;div id="问题现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;数据库实例RSS内存打满，日志有OOM信息，库挂了。这里不分析OOM原因。&lt;/p&gt;
&lt;p&gt;但是起库的时候失败，从日志来看总共起库4、5次都失败：&lt;/p&gt;</description><content:encoded>
&lt;h2 class="relative group"&gt;问题现象
 &lt;div id="问题现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;数据库实例RSS内存打满，日志有OOM信息，库挂了。这里不分析OOM原因。&lt;/p&gt;
&lt;p&gt;但是起库的时候失败，从日志来看总共起库4、5次都失败：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2026-02-12 09:15:21 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;578272&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: FATAL: pre-existing shared memory block &lt;span style="color:#f92672"&gt;(&lt;/span&gt;key 2048, ID 1328250881&lt;span style="color:#f92672"&gt;)&lt;/span&gt; is still in use
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2026-02-12 09:15:21 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;578272&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: HINT: Terminate any old server processes associated with data directory &lt;span style="color:#e6db74"&gt;&amp;#34;/data&amp;#34;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2026-02-12 09:15:21 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;578272&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: LOG: database system is shut down
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2026-02-12 09:21:03 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;658824&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: FATAL: pre-existing shared memory block &lt;span style="color:#f92672"&gt;(&lt;/span&gt;key 2048, ID 1328250881&lt;span style="color:#f92672"&gt;)&lt;/span&gt; is still in use
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2026-02-12 09:21:03 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;658824&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: HINT: Terminate any old server processes associated with data directory &lt;span style="color:#e6db74"&gt;&amp;#34;/data&amp;#34;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2026-02-12 09:21:03 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;658824&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: LOG: database system is shut down
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2026-02-12 09:31:12 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;794791&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: LOG: redirecting log output to logging collector process
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2026-02-12 09:31:12 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;794791&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: HINT: Future log output will appear in directory &lt;span style="color:#e6db74"&gt;&amp;#34;/data/pg_log&amp;#34;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2026-02-12 09:31:37 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;801049&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: FATAL: lock file &lt;span style="color:#e6db74"&gt;&amp;#34;postmaster.pid&amp;#34;&lt;/span&gt; already exists
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2026-02-12 09:31:37 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;801049&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: HINT: Is another postmaster &lt;span style="color:#f92672"&gt;(&lt;/span&gt;PID 794791&lt;span style="color:#f92672"&gt;)&lt;/span&gt; running in data directory &lt;span style="color:#e6db74"&gt;&amp;#34;/data&amp;#34;&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2026-02-12 09:32:34 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;814396&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: FATAL: lock file &lt;span style="color:#e6db74"&gt;&amp;#34;postmaster.pid&amp;#34;&lt;/span&gt; already exists
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2026-02-12 09:32:34 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;814396&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: HINT: Is another postmaster &lt;span style="color:#f92672"&gt;(&lt;/span&gt;PID 794791&lt;span style="color:#f92672"&gt;)&lt;/span&gt; running in data directory &lt;span style="color:#e6db74"&gt;&amp;#34;/data&amp;#34;&lt;/span&gt;?&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;启动成功是因为DBA在起库前执行&lt;code&gt;ipcrm -m xxx&lt;/code&gt;，然后启动成功的。&lt;/p&gt;
&lt;p&gt;虽然快速解决问题，但是仍有很多疑问：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;为什么这种场景在现实种不算太多见？&lt;/li&gt;
&lt;li&gt;start.log起库报错有2类，分别对应什么操作和逻辑？&lt;/li&gt;
&lt;li&gt;如果PM都不在了共享内存还可以存在吗？&lt;/li&gt;
&lt;li&gt;这段共享内存如何定位和清理？&lt;/li&gt;
&lt;li&gt;PG共享内存有多段，这段共享内存是哪一段？&lt;/li&gt;
&lt;li&gt;除了ipcrm -m还有其他起库办法吗&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;报错分析：&lt;code&gt;pre-existing shared memory block&lt;/code&gt;
 &lt;div id="报错分析pre-existing-shared-memory-block" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%8a%a5%e9%94%99%e5%88%86%e6%9e%90pre-existing-shared-memory-block" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;3种共享内存
 &lt;div id="3种共享内存" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#3%e7%a7%8d%e5%85%b1%e4%ba%ab%e5%86%85%e5%ad%98" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;正常来说，PG起库后共享内存有三段。&lt;/p&gt;
&lt;p&gt;以默认“&lt;code&gt;shared_memory_type='mmap'&lt;/code&gt;+未使用大页”为例：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## 从PG申请的虚拟内存查看PG真实使用共享内存&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cat /proc/&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;head -1 $PGDATA/postmaster.pid&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;/smaps | grep -E &lt;span style="color:#e6db74"&gt;&amp;#34;\-s&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2b61b0563000-2b61b0564000 rw-s &lt;span style="color:#ae81ff"&gt;00000000&lt;/span&gt; 00:04 &lt;span style="color:#ae81ff"&gt;116293664&lt;/span&gt; /SYSV00001000 &lt;span style="color:#f92672"&gt;(&lt;/span&gt;deleted&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2b61b057f000-2b61b05b3000 rw-s &lt;span style="color:#ae81ff"&gt;00000000&lt;/span&gt; 00:12 &lt;span style="color:#ae81ff"&gt;1501001168&lt;/span&gt; /dev/shm/PostgreSQL.1193490778
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2b61bbac2000-2b61fa67a000 rw-s &lt;span style="color:#ae81ff"&gt;00000000&lt;/span&gt; 00:04 &lt;span style="color:#ae81ff"&gt;1500999610&lt;/span&gt; /dev/zero &lt;span style="color:#f92672"&gt;(&lt;/span&gt;deleted&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;如上所示，从上往下分别是&lt;strong&gt;SYSV起库使用的共享内存&lt;/strong&gt;、&lt;strong&gt;并行计算使用的共享内存&lt;/strong&gt;、&lt;strong&gt;sharedbuffers使用的共享内存&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;如果sharedbuffers使用了大页，或者sharedbuffers type是SYSV而不是mmap，输出会稍微有些区别。&lt;/p&gt;
&lt;p&gt;大页：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2aaaaac00000-2aba9ca00000 rw-s &lt;span style="color:#ae81ff"&gt;00000000&lt;/span&gt; 00:0e &lt;span style="color:#ae81ff"&gt;48453452&lt;/span&gt; /anon_hugepage &lt;span style="color:#f92672"&gt;(&lt;/span&gt;deleted&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2b08f2eea000-2b08f2eeb000 rw-s &lt;span style="color:#ae81ff"&gt;00000000&lt;/span&gt; 00:04 &lt;span style="color:#ae81ff"&gt;50692152&lt;/span&gt; /SYSV00001000 &lt;span style="color:#f92672"&gt;(&lt;/span&gt;deleted&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2b08f2f05000-2b08f302d000 rw-s &lt;span style="color:#ae81ff"&gt;00000000&lt;/span&gt; 00:12 &lt;span style="color:#ae81ff"&gt;48436142&lt;/span&gt; /dev/shm/PostgreSQL.1345689218&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;shared_memory_type = &amp;lsquo;sysv&amp;rsquo;：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2b03b3ceb000-2b03b3d1f000 rw-s &lt;span style="color:#ae81ff"&gt;00000000&lt;/span&gt; 00:12 &lt;span style="color:#ae81ff"&gt;1572332304&lt;/span&gt; /dev/shm/PostgreSQL.2883611352
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2b03bf0c2000-2b03fdc7a000 rw-s &lt;span style="color:#ae81ff"&gt;00000000&lt;/span&gt; 00:04 &lt;span style="color:#ae81ff"&gt;143917075&lt;/span&gt; /SYSV00001000 &lt;span style="color:#f92672"&gt;(&lt;/span&gt;deleted&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;汇总如下：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;PG共享内存配置&lt;/th&gt;
 &lt;th&gt;smaps共享内存段数&lt;/th&gt;
 &lt;th&gt;sharedbuffers smaps&lt;/th&gt;
 &lt;th&gt;sysv smaps&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;shared_memory_type=mmap，没有大页&lt;/td&gt;
 &lt;td&gt;3段共享内存&lt;/td&gt;
 &lt;td&gt;/dev/zero&lt;/td&gt;
 &lt;td&gt;/SYSV00001000&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;shared_memory_type=sysv，没有大页&lt;/td&gt;
 &lt;td&gt;2段共享内存&lt;/td&gt;
 &lt;td&gt;/SYSV00001000&lt;/td&gt;
 &lt;td&gt;/SYSV00001000&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;shared_memory_type=mmap，有大页&lt;/td&gt;
 &lt;td&gt;3段共享内存&lt;/td&gt;
 &lt;td&gt;/anon_hugepage&lt;/td&gt;
 &lt;td&gt;/SYSV00001000&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;shared_memory_type=sysv，有大页&lt;/td&gt;
 &lt;td&gt;不支持&lt;/td&gt;
 &lt;td&gt;不支持&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;那么现在问题来了，报错分析：&lt;code&gt;pre-existing shared memory block&lt;/code&gt;时对应的哪个共享内存？&lt;/p&gt;

&lt;h3 class="relative group"&gt;源码分析
 &lt;div id="源码分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%ba%90%e7%a0%81%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;源码搜报错很容易找到关键代码位置：&lt;code&gt;src/backend/port/sysv_shmem.c&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;首先理解sysv shmem是干嘛的，以下截取自零散的readme：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;We still require a SysV shmem block to
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; * exist, though, because mmap&amp;#39;d shmem provides no way to find out how
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; * many processes are attached, which we need for interlocking purposes.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; * As of PostgreSQL 9.3, we normally allocate only a very small amount of
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; * System V shared memory, and only for the purposes of providing an
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; * interlock to protect the data directory. The real shared memory block
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; * is allocated using mmap(). This works around the problem that many
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; * systems have very low limits on the amount of System V shared memory
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; * that can be allocated. Even a limit of a few megabytes will be enough
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; * to run many copies of PostgreSQL without needing to adjust system settings.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;sysv shmem可以找共享内存是否是attached，mmap不能实现此功能&lt;/li&gt;
&lt;li&gt;这段&lt;strong&gt;sysv shmem是用来保护datadir的&lt;/strong&gt;；shared buffer用的是mmap（默认）不是sysv&lt;/li&gt;
&lt;li&gt;这段sysv shmem非常小（从虚拟内存地址可以看出申请的是4K=2b61b0563000-2b61b0564000）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;再看shm的状态enum：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;typedef&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;enum&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	SHMSTATE_ANALYSIS_FAILURE,	&lt;span style="color:#75715e"&gt;/* unexpected failure to analyze the ID */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	SHMSTATE_ATTACHED,			&lt;span style="color:#75715e"&gt;/* pertinent to DataDir, has attached PIDs */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	SHMSTATE_ENOENT,			&lt;span style="color:#75715e"&gt;/* no segment of that ID */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	SHMSTATE_FOREIGN,			&lt;span style="color:#75715e"&gt;/* exists, but not pertinent to DataDir */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	SHMSTATE_UNATTACHED			&lt;span style="color:#75715e"&gt;/* pertinent to DataDir, no attached PIDs */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} IpcMemoryState;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;主要是关注ATTACHED,FOREIGN,UNATTACHED。&lt;/p&gt;
&lt;p&gt;sysv shmem是用来保护datadir目录的，比如常见的场景是要确认这个目录不会被跑2个实例。既然有shmem共享内存，那么因为各种奇怪原因，这个共享内存也有可能不是这个目录或者这个进程的，所有是FOREIGN状态。如果共享内存对应到datadir了，但没有进程在运行，那么应该是UNATTACHED，有进程运行那么是ATTACHED。&lt;/p&gt;
&lt;p&gt;这时再来看&lt;code&gt;PGSharedMemoryCreate&lt;/code&gt;函数抛出的报错：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PGShmemHeader &lt;span style="color:#f92672"&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;PGSharedMemoryCreate&lt;/span&gt;(Size size,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					 PGShmemHeader &lt;span style="color:#f92672"&gt;**&lt;/span&gt;shim)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (;;) &lt;span style="color:#75715e"&gt;//死循环
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{..
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; shmid &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;shmget&lt;/span&gt;(NextShmemSegID, &lt;span style="color:#66d9ef"&gt;sizeof&lt;/span&gt;(PGShmemHeader), &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);&lt;span style="color:#75715e"&gt;//shmget获取shmem共享内存并返回shmid
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (shmid &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			oldhdr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; NULL;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			state &lt;span style="color:#f92672"&gt;=&lt;/span&gt; SHMSTATE_FOREIGN;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			state &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;PGSharedMemoryAttach&lt;/span&gt;(shmid, NULL, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;oldhdr);&lt;span style="color:#75715e"&gt;//找到这段shmem共享内存的状态
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; (state)&lt;span style="color:#75715e"&gt;//根据共享内存的状态执行不同的动作
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{ 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...&lt;span style="color:#75715e"&gt;//这里只展示了2种，shm有attach和没有attach
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; SHMSTATE_ATTACHED: &lt;span style="color:#75715e"&gt;//shm有attach的情况，抛出报错（也就是问题现象出现的报错）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;ereport&lt;/span&gt;(FATAL,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						(&lt;span style="color:#a6e22e"&gt;errcode&lt;/span&gt;(ERRCODE_LOCK_FILE_EXISTS),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						 &lt;span style="color:#a6e22e"&gt;errmsg&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;pre-existing shared memory block (key %lu, ID %lu) is still in use&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;								(&lt;span style="color:#66d9ef"&gt;unsigned&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;long&lt;/span&gt;) NextShmemSegID,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;								(&lt;span style="color:#66d9ef"&gt;unsigned&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;long&lt;/span&gt;) shmid),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						 &lt;span style="color:#a6e22e"&gt;errhint&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Terminate any old server processes associated with data directory &lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;%s&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;.&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;								 DataDir)));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; SHMSTATE_UNATTACHED:&lt;span style="color:#75715e"&gt;//shm是unattach的
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 * The segment pertains to DataDir, and every process that had
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 * used it has died or detached. Zap it, if possible, and any
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 * associated dynamic shared memory segments, as well. This
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 * shouldn&amp;#39;t fail, but if it does, assume the segment belongs
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 * to someone else after all, and try the next candidate.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 * Otherwise, try again to create the segment. That may fail
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 * if some other process creates the same shmem key before we
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 * do, in which case we&amp;#39;ll try the next key.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//代表内存段关联Data目录，且没有进程还持有这个段
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (oldhdr&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;dsm_control &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					&lt;span style="color:#a6e22e"&gt;dsm_cleanup_using_control_segment&lt;/span&gt;(oldhdr&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;dsm_control);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;shmctl&lt;/span&gt;(shmid, IPC_RMID, NULL) &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					NextShmemSegID&lt;span style="color:#f92672"&gt;++&lt;/span&gt;; &lt;span style="color:#75715e"&gt;//注意这里的ShmemSegID递增循环
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;可以看到shmem attached时会抛出报错。如果没有attach，会无限循环尝试清理这段共享内存并shmemsegid+1申请新的共享内存。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;第一种情况对应这个故障&lt;/li&gt;
&lt;li&gt;第二种情况对应实例崩溃仍然可以正常起库&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 class="relative group"&gt;sysv shmem
 &lt;div id="sysv-shmem" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#sysv-shmem" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;PG10及以后postmaster.pid，sysv_shmem相关的逻辑大改，10以后基本没有变过。本文只分析了10以后的逻辑。&lt;/p&gt;
&lt;p&gt;pidfile.h:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define LOCK_FILE_LINE_SHMEM_KEY	7&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;sysv_shmem.c，InternalIpcMemoryCreate()：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;char&lt;/span&gt;		line[&lt;span style="color:#ae81ff"&gt;64&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;sprintf&lt;/span&gt;(line, &lt;span style="color:#e6db74"&gt;&amp;#34;%9lu %9lu&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				(&lt;span style="color:#66d9ef"&gt;unsigned&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;long&lt;/span&gt;) memKey, (&lt;span style="color:#66d9ef"&gt;unsigned&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;long&lt;/span&gt;) shmid);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;AddToDataDirLockFile&lt;/span&gt;(LOCK_FILE_LINE_SHMEM_KEY, line);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;从源码可以看出，shmem信息保存在postmaster.pid文件第七行，分别写的是shmkey和shmid。&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; cat postmaster.pid 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;242712&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/data
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;1772698474&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;8531&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/tmp
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;0.0.0.0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;143917078&lt;/span&gt; &lt;span style="color:#75715e"&gt;# &amp;lt;----here&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ready&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 class="relative group"&gt;什么是shmkey和shmid
 &lt;div id="什么是shmkey和shmid" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%bb%80%e4%b9%88%e6%98%afshmkey%e5%92%8cshmid" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;在pg源码中是这样调用的，InternalIpcMemoryCreate()：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			shmid &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;shmget&lt;/span&gt;(memKey, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, IPC_CREAT &lt;span style="color:#f92672"&gt;|&lt;/span&gt; IPC_EXCL &lt;span style="color:#f92672"&gt;|&lt;/span&gt; IPCProtection);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;PG以shmkey/memkey为种子key，向内核申请shmem并返回唯一标识符shmid&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;shmid高度依赖服务器或者说服务器内存的状态。对于PG来说，快速重启实例，前后的shmid可能会相同或者+1，这跟linux内核机制相关；服务器重启那就完全不一样。&lt;/p&gt;
&lt;p&gt;可以这样增加理解度：&lt;strong&gt;无论服务器是否重启，shmkey/memkey都可以是固定值，因为毕竟是用户输入（即PG）；而在服务器重启前后，即便传入同一shmkey，获取的shmid不太可能是同一值。&lt;/strong&gt;&lt;/p&gt;

&lt;h4 class="relative group"&gt;PG是怎么拿shmkey的
 &lt;div id="pg是怎么拿shmkey的" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#pg%e6%98%af%e6%80%8e%e4%b9%88%e6%8b%bfshmkey%e7%9a%84" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;PGSharedMemoryCreate()：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * We use the data directory&amp;#39;s ID info (inode and device numbers) to
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * positively identify shmem segments associated with this data dir, and
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * also as seeds for searching for a free shmem key.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;stat&lt;/span&gt;(DataDir, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;statbuf) &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;ereport&lt;/span&gt;(FATAL,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				(&lt;span style="color:#a6e22e"&gt;errcode_for_file_access&lt;/span&gt;(),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				 &lt;span style="color:#a6e22e"&gt;errmsg&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;could not stat data directory &lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;%s&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;: %m&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						DataDir)));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * Loop till we find a free IPC key. Trust CreateDataDirLockFile() to
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * ensure no more than one postmaster per data directory can enter this
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * loop simultaneously. (CreateDataDirLockFile() does not entirely ensure
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * that, but prefer fixing it over coping here.)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	NextShmemSegID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; statbuf.st_ino;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (;;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		IpcMemoryId shmid;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		PGShmemHeader &lt;span style="color:#f92672"&gt;*&lt;/span&gt;oldhdr;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		IpcMemoryState state;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* Try to create new segment */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		memAddress &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;InternalIpcMemoryCreate&lt;/span&gt;(NextShmemSegID, sysvsize);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (memAddress)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;				&lt;span style="color:#75715e"&gt;/* successful create and attach */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* Check shared memory and possibly remove and recreate */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * shmget() failure is typically EACCES, hence SHMSTATE_FOREIGN.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * ENOENT, a narrow possibility, implies SHMSTATE_ENOENT, but one can
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * safely treat SHMSTATE_ENOENT like SHMSTATE_FOREIGN.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		shmid &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;shmget&lt;/span&gt;(NextShmemSegID, &lt;span style="color:#66d9ef"&gt;sizeof&lt;/span&gt;(PGShmemHeader), &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;PG通过stat获取datadir的状态，其中包含datadir的inode，PG直接将datadir.inode当作shmkey。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;在PG中shmem key跟datadir的inode强相关，一般情况下shmem key=datadir inode&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;验证示例：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; ls -id $PGDATA
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; /lzlcloud/pg8574/data
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; cat postmaster.pid |head -7|tail -1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;143917090&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;可以看到datadir.inode=shmkey=4096。&lt;/p&gt;

&lt;h4 class="relative group"&gt;PG在云环境下的shmkey
 &lt;div id="pg在云环境下的shmkey" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#pg%e5%9c%a8%e4%ba%91%e7%8e%af%e5%a2%83%e4%b8%8b%e7%9a%84shmkey" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;上面说一般情况shmid=datadir.inode，实际上这在云环境中基本不是这个情况。&lt;/p&gt;
&lt;p&gt;我们的云环境：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; ls -id /lzlcloud/pg8298/data
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; /lzlcloud/pg8298/data
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; ls -id /lzlcloud/pg8388/data
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; /lzlcloud/pg8388/data
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; ls -id /lzlcloud/pg8095/data
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; /lzlcloud/pg8095/data&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; cat /lzlcloud/pg8298/data/postmaster.pid|head -7|tail -1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;971833391&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; cat /lzlcloud/pg8388/data/postmaster.pid|head -7|tail -1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;4097&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;62128161&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; cat /lzlcloud/pg8095/data/postmaster.pid|head -7|tail -1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;4098&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;143163441&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;data盘dir的inode都是4096，而shmkey是4096、4097、4098&lt;/p&gt;
&lt;p&gt;why?&lt;/p&gt;
&lt;p&gt;inode的问题跟磁盘的文件系统有关系：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每个文件系统有独立的inode&lt;/li&gt;
&lt;li&gt;文件系统预留了一些inode，前几位是不能使用的。根据不同的挂载方式，我们data盘真正的inode从4096开始&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;也就是说datadir.inode=4096这是我们云环境磁盘挂载的默认行为。其他环境可能不一样，未深入分析。不过以相同文件系统和相同方式挂载挂载pg datadir的话，仍有可能inode数值相等。&lt;/p&gt;
&lt;p&gt;shmkey的问题跟PG源码相关,PGSharedMemoryCreate()：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (;;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{	
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; NextShmemSegID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; statbuf.st_ino;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		shmid &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;shmget&lt;/span&gt;(NextShmemSegID, &lt;span style="color:#66d9ef"&gt;sizeof&lt;/span&gt;(PGShmemHeader), &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; (state)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; SHMSTATE_FOREIGN:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				NextShmemSegID&lt;span style="color:#f92672"&gt;++&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;本来shmkey=datadir.inode，但是由于可能申请到shmem是foreign的，所以shmkey+1再申请一次。&lt;/p&gt;
&lt;p&gt;例如postmaster.pid文件shmkey=4097的那个实例，它起库时shmkey=4096，但是发现shmid那个内存段被其他实例使用了（就是另一个shmkey=4096的PG实例），它让shmkey+1再申请了另一个shmid共享内存段。&lt;/p&gt;
&lt;p&gt;同理shmkey=4098的那个实例加了2次才找到空闲的shmkey对应的shmid。&lt;/p&gt;

&lt;h3 class="relative group"&gt;shmid的关联性
 &lt;div id="shmid的关联性" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#shmid%e7%9a%84%e5%85%b3%e8%81%94%e6%80%a7" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;sysv的shmid可以在&lt;strong&gt;起库的报错日志&lt;/strong&gt;、&lt;strong&gt;postmaster.pid文件第7行&lt;/strong&gt;、&lt;strong&gt;虚拟内存地址smaps&lt;/strong&gt;中均可以找到，并通过sysv共享内存命令的&lt;code&gt;ipcs&lt;/code&gt;命令查看和&lt;code&gt;ipcrm&lt;/code&gt;命令清理。&lt;/p&gt;
&lt;p&gt;示例：注意以下shmid=143917078&lt;/p&gt;
&lt;p&gt;起库报错日志：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pg_ctl: another server might be running; trying to start server anyway
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;waiting &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; server to start....2026-03-05 16:02:19 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;262388&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: FATAL: pre-existing shared memory block &lt;span style="color:#f92672"&gt;(&lt;/span&gt;key 4096, ID 143917078&lt;span style="color:#f92672"&gt;)&lt;/span&gt; is still in use&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;postmaster.pid文件第七行：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; cat postmaster.pid |head -7|tail -1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;143917078&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;虚拟内存smaps：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cat /proc/&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;head -1 $PGDATA/postmaster.pid&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;/smaps | grep -E &lt;span style="color:#e6db74"&gt;&amp;#34;\-s&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2ad2b5189000-2ad2b518a000 rw-s &lt;span style="color:#ae81ff"&gt;00000000&lt;/span&gt; 00:04 &lt;span style="color:#ae81ff"&gt;143917078&lt;/span&gt; /SYSV00001000 &lt;span style="color:#f92672"&gt;(&lt;/span&gt;deleted&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;通过shmid sysv共享内存id查看和清理：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ipcs -m -i &lt;span style="color:#ae81ff"&gt;143917078&lt;/span&gt; &lt;span style="color:#75715e"&gt;#清理：ipcrm -m shmid&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Shared memory Segment shmid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;143917078&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;uid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; gid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; cuid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; cgid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mode&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0600&lt;/span&gt; access_perms&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0600&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bytes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt; lpid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;242712&lt;/span&gt; cpid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;242712&lt;/span&gt; nattch&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;att_time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Thu Mar &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; 16:14:51 &lt;span style="color:#ae81ff"&gt;2026&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;det_time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Thu Mar &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; 16:14:49 &lt;span style="color:#ae81ff"&gt;2026&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;change_time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Thu Mar &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; 16:14:34 &lt;span style="color:#ae81ff"&gt;2026&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 class="relative group"&gt;测试
 &lt;div id="测试" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%b5%8b%e8%af%95" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;

&lt;h4 class="relative group"&gt;生产问题复现
 &lt;div id="生产问题复现" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%94%9f%e4%ba%a7%e9%97%ae%e9%a2%98%e5%a4%8d%e7%8e%b0" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;持有一个backend进程永不退出，kill -9 PM&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; cat postmaster.pid
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;143917076&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; ipcs -m -i &lt;span style="color:#ae81ff"&gt;143917076&lt;/span&gt; &lt;span style="color:#75715e"&gt;#shmem id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Shared memory Segment shmid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;143917076&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;uid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; gid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; cuid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; cgid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mode&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0600&lt;/span&gt; access_perms&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0600&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bytes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt; lpid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;241567&lt;/span&gt; cpid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;64757&lt;/span&gt; nattch&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; kill -stop &lt;span style="color:#ae81ff"&gt;107648&lt;/span&gt; &lt;span style="color:#75715e"&gt;#任意一个backend&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; kill -9 &lt;span style="color:#ae81ff"&gt;64757&lt;/span&gt; &lt;span style="color:#75715e"&gt;#postmaster或者其他的&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; ipcs -m -i &lt;span style="color:#ae81ff"&gt;143917076&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Shared memory Segment shmid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;143917076&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;uid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; gid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; cuid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; cgid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mode&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0600&lt;/span&gt; access_perms&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0600&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bytes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt; lpid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;252283&lt;/span&gt; cpid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;64757&lt;/span&gt; nattch&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#75715e"&gt;#nattch != 0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; pg_ctl start -D $PGDATA
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pg_ctl: another server might be running; trying to start server anyway
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;waiting &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; server to start....2026-03-05 16:02:19 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;262388&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: FATAL: pre-existing shared memory block &lt;span style="color:#f92672"&gt;(&lt;/span&gt;key 4096, ID 143917076&lt;span style="color:#f92672"&gt;)&lt;/span&gt; is still in use
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2026-03-05 16:02:19 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;262388&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: HINT: Terminate any old server processes associated with data directory &lt;span style="color:#e6db74"&gt;&amp;#34;/data&amp;#34;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stopped waiting
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pg_ctl: could not start server&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;nattach=1，实例无法启动。&lt;/p&gt;

&lt;h4 class="relative group"&gt;实例奔溃正常起库
 &lt;div id="实例奔溃正常起库" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%ae%9e%e4%be%8b%e5%a5%94%e6%ba%83%e6%ad%a3%e5%b8%b8%e8%b5%b7%e5%ba%93" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;其实就是kill实例然后启动&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; cat postmaster.pid 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;143917077&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; ipcs -m -i &lt;span style="color:#ae81ff"&gt;143917077&lt;/span&gt; &lt;span style="color:#75715e"&gt;#shmem id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Shared memory Segment shmid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;143917077&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;uid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; gid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; cuid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; cgid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mode&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0600&lt;/span&gt; access_perms&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0600&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bytes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt; lpid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;154800&lt;/span&gt; cpid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;134329&lt;/span&gt; nattch&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; kill -9 &lt;span style="color:#ae81ff"&gt;134329&lt;/span&gt; &lt;span style="color:#75715e"&gt;#postmaster或者其他的&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; cat postmaster.pid 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;143917077&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; ipcs -m -i &lt;span style="color:#ae81ff"&gt;143917077&lt;/span&gt; &lt;span style="color:#75715e"&gt;#shmem id没有改变，shmem仍然存在&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Shared memory Segment shmid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;143917077&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;uid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; gid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; cuid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; cgid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mode&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0600&lt;/span&gt; access_perms&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0600&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bytes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt; lpid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;169360&lt;/span&gt; cpid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;134329&lt;/span&gt; nattch&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#75715e"&gt;#nattch=0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; ipcs -m -i &lt;span style="color:#ae81ff"&gt;143917077&lt;/span&gt; &lt;span style="color:#75715e"&gt;#shmem id没有改变，shmem仍然存在&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; pg_ctl start -D $PGDATA &lt;span style="color:#75715e"&gt;# 起库成功&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pg_ctl: another server might be running; trying to start server anyway
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;waiting &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; server to start....2026-03-05 16:14:34 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;242712&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: LOG: redirecting log output to logging collector process
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2026-03-05 16:14:34 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;242712&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: HINT: Future log output will appear in directory &lt;span style="color:#e6db74"&gt;&amp;#34;/data/pg_log&amp;#34;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;server started
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; ipcs -m -i &lt;span style="color:#ae81ff"&gt;143917077&lt;/span&gt; &lt;span style="color:#75715e"&gt;#残留的shmem起库时被清理&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ipcs: id &lt;span style="color:#ae81ff"&gt;143917077&lt;/span&gt; not found
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; ipcs -m -i &lt;span style="color:#ae81ff"&gt;143917078&lt;/span&gt; &lt;span style="color:#75715e"&gt;#shmemid起库时被+1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Shared memory Segment shmid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;143917078&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;uid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; gid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; cuid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; cgid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mode&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0600&lt;/span&gt; access_perms&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0600&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bytes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt; lpid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;273571&lt;/span&gt; cpid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;242712&lt;/span&gt; nattch&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;26&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; cat postmaster.pid &lt;span style="color:#75715e"&gt;# shmkey不变，shmid+1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;143917078&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;正常kill -9然后启动，可以正常启动，残留的shmem会在启动时被清理。shmkey不变是因为inode=4096且shmkey=4096没有被占用，shmid+1这是linux内核行为，至少说明不是使用的同一段shmem。&lt;/p&gt;

&lt;h4 class="relative group"&gt;持有文件但不持有shmem
 &lt;div id="持有文件但不持有shmem" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%8c%81%e6%9c%89%e6%96%87%e4%bb%b6%e4%bd%86%e4%b8%8d%e6%8c%81%e6%9c%89shmem" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;因为起库跟datadir inode相关，inode跟shmem id相关，起库本质上是在&lt;strong&gt;检查shmem是不是被其他进程持有，而不是文件fd是否还被其他进程持有&lt;/strong&gt;。所以这里测试不持有共享内存但持有文件fd的进程logger。&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ cat /proc/77300/smaps | grep -E &lt;span style="color:#e6db74"&gt;&amp;#34;\-s&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;#这是logger进程，检查它没有用共享内存&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ kill -stop &lt;span style="color:#ae81ff"&gt;77300&lt;/span&gt; &lt;span style="color:#75715e"&gt;#stop logger&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ kill -9 &lt;span style="color:#ae81ff"&gt;77076&lt;/span&gt; &lt;span style="color:#75715e"&gt;#kill -9 pm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ cat postmaster.pid &lt;span style="color:#75715e"&gt;#文件仍在&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;77076&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/lzlcloud/pg8531/data
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;1772700343&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;8531&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/tmp
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;0.0.0.0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;143917080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ready 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ ipcs -m -i &lt;span style="color:#ae81ff"&gt;143917080&lt;/span&gt; &lt;span style="color:#75715e"&gt;#共享内存仍在&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Shared memory Segment shmid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;143917080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;uid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; gid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; cuid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; cgid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mode&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0600&lt;/span&gt; access_perms&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0600&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bytes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt; lpid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;77319&lt;/span&gt; cpid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;77076&lt;/span&gt; nattch&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;att_time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Thu Mar &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; 17:27:11 &lt;span style="color:#ae81ff"&gt;2026&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;det_time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Thu Mar &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; 17:27:15 &lt;span style="color:#ae81ff"&gt;2026&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;change_time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Thu Mar &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; 16:45:43 &lt;span style="color:#ae81ff"&gt;2026&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ ps -ef|grep &lt;span style="color:#ae81ff"&gt;77300&lt;/span&gt; &lt;span style="color:#75715e"&gt;#进程仍在&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;postgres &lt;span style="color:#ae81ff"&gt;77300&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 16:45 ? 00:00:00 postgresql: lzldb: logger 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;postgres &lt;span style="color:#ae81ff"&gt;135246&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;46622&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 17:27 pts/1 00:00:00 grep --color&lt;span style="color:#f92672"&gt;=&lt;/span&gt;auto &lt;span style="color:#ae81ff"&gt;77300&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ pg_ctl start -D $PGDATA &lt;span style="color:#75715e"&gt;#起库成功&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pg_ctl: another server might be running; trying to start server anyway
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;waiting &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; server to start....2026-03-05 17:27:55 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;140497&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: LOG: redirecting log output to logging collector process
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2026-03-05 17:27:55 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;140497&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: HINT: Future log output will appear in directory &lt;span style="color:#e6db74"&gt;&amp;#34;/data/pg_log&amp;#34;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;server started&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;logger持有data目录下的文件，但不关联共享内存，不会阻止起库&lt;/p&gt;

&lt;h4 class="relative group"&gt;删除postmaster.pid文件起库失败
 &lt;div id="删除postmasterpid文件起库失败" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%88%a0%e9%99%a4postmasterpid%e6%96%87%e4%bb%b6%e8%b5%b7%e5%ba%93%e5%a4%b1%e8%b4%a5" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;流程跟上面差不多：持有1个backend进程，kill -9 PM，删除postmaster.pid文件，起库。&lt;/p&gt;
&lt;p&gt;过程不贴了，结果是起库失败，报错如下：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;waiting &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; server to start....2026-03-06 15:29:48 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;22475&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: FATAL: pre-existing shared memory block &lt;span style="color:#f92672"&gt;(&lt;/span&gt;key 4098, ID 171868173&lt;span style="color:#f92672"&gt;)&lt;/span&gt; is still in use
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2026-03-06 15:29:48 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;22475&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: HINT: Terminate any old server processes associated with data directory &lt;span style="color:#e6db74"&gt;&amp;#34;/data&amp;#34;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2026-03-06 15:29:48 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;22475&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: LOG: database system is shut down&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;可以看出，有僵尸进程持有shmem的情况下，即便删除包含shmid的postmaster.pid文件，PG仍然能找到对应的shmid。&lt;/p&gt;

&lt;h4 class="relative group"&gt;关闭一个其他库，启动当前库
 &lt;div id="关闭一个其他库启动当前库" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%85%b3%e9%97%ad%e4%b8%80%e4%b8%aa%e5%85%b6%e4%bb%96%e5%ba%93%e5%90%af%e5%8a%a8%e5%bd%93%e5%89%8d%e5%ba%93" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;pg会分析2个地方shmid是否是当前的&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;以datadir.inode当作shmkey对应的shmid，或者&lt;code&gt;shmkey++&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;postmaster.pid中的shmid&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;即便直接删除postmaster.pid，PG仍然可以知道shmem是不是被其他进程持有。但是我们可以通过datadir.inode和&lt;code&gt;shmkey++&lt;/code&gt;的特性让他起库。&lt;/p&gt;
&lt;p&gt;因为根据之前分析，我们云环境datadir inode都是4096，shmkey不同是因为源码有&lt;code&gt;shmkey++&lt;/code&gt;的逻辑。所以我们可以：&lt;strong&gt;启动或停止一个datadir.inode=4096的PG库，让当前PG库启动时&lt;code&gt;shmkey++&lt;/code&gt;多一个或者少一个，拿到不同的shmid。&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ kill -stop &lt;span style="color:#ae81ff"&gt;165245&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ kill -9 &lt;span style="color:#ae81ff"&gt;164411&lt;/span&gt; &lt;span style="color:#75715e"&gt;#停当前库并持有一个当前库backend进程&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ pg_ctl stop -D /pg8531/data &lt;span style="color:#75715e"&gt;# 停一个其他库&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;waiting &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; server to shut down.... &lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;server stopped
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ pg_ctl start -D /pg8574/data &lt;span style="color:#75715e"&gt;# 启动当前库，会失败，因为postmaster.pid没有删除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rase_ctl: another server might be running; trying to start server anyway
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;waiting &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; server to start....2026-03-05 18:22:35 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;196209&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: FATAL: pre-existing shared memory block &lt;span style="color:#f92672"&gt;(&lt;/span&gt;key 4097, ID 143917087&lt;span style="color:#f92672"&gt;)&lt;/span&gt; is still in use
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2026-03-05 18:22:35 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;196209&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: HINT: Terminate any old server processes associated with data directory &lt;span style="color:#e6db74"&gt;&amp;#34;/pg8574/data&amp;#34;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stopped waiting
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rase_ctl: could not start server
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Examine the log output.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ mv /lzlcloud/pg8574/data/postmaster.pid&lt;span style="color:#f92672"&gt;{&lt;/span&gt;,.bak&lt;span style="color:#f92672"&gt;}&lt;/span&gt; &lt;span style="color:#75715e"&gt;# 删除当前库的postmaster.pid&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ pg_ctl start -D /lzlcloud/pg8574/data &lt;span style="color:#75715e"&gt;#再起当前库，成功&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2026-03-05 18:23:09 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;207725&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: LOG: redirecting log output to logging collector process
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2026-03-05 18:23:09 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;207725&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: HINT: Future log output will appear in directory &lt;span style="color:#e6db74"&gt;&amp;#34;/lzlcloud/pg8574/data/pg_log&amp;#34;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;server started
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ ipcs -m -i &lt;span style="color:#ae81ff"&gt;143917087&lt;/span&gt; &lt;span style="color:#75715e"&gt;#shmid对应的sysv共享内存仍然被我们持有&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Shared memory Segment shmid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;143917087&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;uid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; gid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; cuid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; cgid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mode&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0600&lt;/span&gt; access_perms&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0600&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bytes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt; lpid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;196209&lt;/span&gt; cpid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;164411&lt;/span&gt; nattch&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;att_time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Thu Mar &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; 18:22:35 &lt;span style="color:#ae81ff"&gt;2026&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;det_time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Thu Mar &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; 18:22:35 &lt;span style="color:#ae81ff"&gt;2026&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;change_time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Thu Mar &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; 18:21:04 &lt;span style="color:#ae81ff"&gt;2026&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;可以启动，当前库共享内存申请了另一块，之前那个共享内存没有被清理。这就是在云环境下关其他库启动当前库的骚操作。&lt;/p&gt;
&lt;p&gt;这里有个小小的前提，关的其他库不仅要inode=当前库inode，还要其他库shmkey&amp;lt;当前库shmkey。&lt;/p&gt;

&lt;h2 class="relative group"&gt;报错分析：&lt;code&gt;lock file &amp;quot;postmaster.pid&amp;quot; already exists&lt;/code&gt;
 &lt;div id="报错分析lock-file-postmasterpid-already-exists" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%8a%a5%e9%94%99%e5%88%86%e6%9e%90lock-file-postmasterpid-already-exists" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;这个问题比“共享内存已存在”简单多了。&lt;/p&gt;
&lt;p&gt;起库时本身就会检查lock file、lock file中的pid，CreateLockFile():&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (other_pid &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; my_pid &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; other_pid &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; my_p_pid &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			other_pid &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; my_gp_pid)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;kill&lt;/span&gt;(other_pid, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				(errno &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; ESRCH &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; errno &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; EPERM))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#75715e"&gt;/* lockfile belongs to a live process */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;ereport&lt;/span&gt;(FATAL,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						(&lt;span style="color:#a6e22e"&gt;errcode&lt;/span&gt;(ERRCODE_LOCK_FILE_EXISTS),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						 &lt;span style="color:#a6e22e"&gt;errmsg&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;lock file &lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;%s&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt; already exists&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;								filename),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						 isDDLock &lt;span style="color:#f92672"&gt;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						 (encoded_pid &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						 &lt;span style="color:#a6e22e"&gt;errhint&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Is another postgres (PID %d) running in data directory &lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;%s&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;?&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;								 (&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) other_pid, refName) &lt;span style="color:#f92672"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						 &lt;span style="color:#a6e22e"&gt;errhint&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Is another postmaster (PID %d) running in data directory &lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;%s&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;?&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;								 (&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) other_pid, refName)) &lt;span style="color:#f92672"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						 (encoded_pid &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						 &lt;span style="color:#a6e22e"&gt;errhint&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Is another postgres (PID %d) using socket file &lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;%s&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;?&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;								 (&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) other_pid, refName) &lt;span style="color:#f92672"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						 &lt;span style="color:#a6e22e"&gt;errhint&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Is another postmaster (PID %d) using socket file &lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;%s&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;?&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;								 (&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) other_pid, refName))));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;测试就更简单，在库启动的时候再启动一次：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ pg_ctl start -D /pg8531/data
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pg_ctl: another server might be running; trying to start server anyway
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;waiting &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; server to start....2026-03-06 15:59:05 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;89145&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: FATAL: lock file &lt;span style="color:#e6db74"&gt;&amp;#34;postmaster.pid&amp;#34;&lt;/span&gt; already exists
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2026-03-06 15:59:05 CST::@:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;89145&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: HINT: Is another postmaster &lt;span style="color:#f92672"&gt;(&lt;/span&gt;PID 255500&lt;span style="color:#f92672"&gt;)&lt;/span&gt; running in data directory &lt;span style="color:#e6db74"&gt;&amp;#34;/pg8531/data&amp;#34;&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stopped waiting
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pg_ctl: could not start server
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Examine the log output.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;所以故障时的start.log后面几个报错是因为库已经启动了，多启动了几次。&lt;/p&gt;

&lt;h2 class="relative group"&gt;总结
 &lt;div id="总结" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%80%bb%e7%bb%93" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;PG在起库时，会先开辟一个sysv shmem（不是mmap对应的share buffers）以锁定datadir。锁定是通过datadir的inode号当作shmkey通过shmget申请的，并返回shmem唯一标识符shmid。由于可能申请的shmem被其他进程使用，PG会让&lt;code&gt;shmkey++&lt;/code&gt;无限循环指到申请到没有被人占用的shmem。postmaster.pid第七行分别保存shmkey和shmid。在云环境下通常可以看到共享PG实例的shmkey递增的现象，这是因为data盘挂载方式相同使用了相同的inode，&lt;code&gt;shmkey++&lt;/code&gt;导致。&lt;/p&gt;
&lt;p&gt;如果PG实例被意外干掉，shmem不会被清理，正常情况下没有僵尸进程持有共享内存，那么起库会清理这段shmem并正常起库；异常情况下僵尸进程持有共享内存，起库会失败，此时需要介入处理。&lt;/p&gt;
&lt;p&gt;推荐的处理方式：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ipcrm -m（最推荐）&lt;/li&gt;
&lt;li&gt;lsof找到僵尸进程并kill&lt;/li&gt;
&lt;li&gt;重启主机&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;不推荐但可以起库的方式：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;mv postmaster.pid+关闭一个其他PG库（其他PG库的shmkey&amp;lt;当前PG库）&lt;/li&gt;
&lt;li&gt;mv postmaster.pid+重新挂载data盘并改变inode&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;最后回答开头的问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;为什么这种场景在现实种不算太多见？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;实例异常宕机+仍然有僵尸进程没有被清理。有些情况是异常宕机没有僵尸进程，正常起库就行了。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;start.log起库报错有2类，分别对应什么操作和逻辑？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;共享内存被占用的报错是因为实例异常宕机+仍然有僵尸进程；postmaster.pid存在的报错是因为起库多次&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如果PM都不在了共享内存还可以存在吗？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;PM都不在了共享内存可以存在，PG的进程不一定会自己跑挂或者被OS处理；但是所有进程都不在了共享内存应该不存在&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;这段共享内存如何定位和清理？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;起库的start.log可以找到shmid，&lt;code&gt;ipcrm -m $shmid&lt;/code&gt;命令可以清理。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PG共享内存有多段，这段共享内存是哪一段？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;sysv shmem，用于保护datadir，一定存在，参考“三种共享内存”部分。与mmap下的sharebuffers是2个东西。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可以通过inode或者文件找到对应的shmem吗？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;LINUX在用户态没有提供通过inode或者文件找到对应shmem的接口（这句话AI含量100%，经过多个模型交叉验证）。PG是通过datadir的inode当作种子shmkey去申请的shmem共享内存，本质上不是通过inode直接找到对应的shmem，PG对shmem共享内存使用自己的寻找机制，但不绝对对应，shkey++就是一个折衷起库逻辑。&lt;/p&gt;</content:encoded></item><item><title>pg数据库运维经验2025</title><link>https://lastdba.com/2026/01/11/pg%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%90%E7%BB%B4%E7%BB%8F%E9%AA%8C2025/</link><pubDate>Sun, 11 Jan 2026 00:00:00 +0000</pubDate><guid>https://lastdba.com/2026/01/11/pg%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%90%E7%BB%B4%E7%BB%8F%E9%AA%8C2025/</guid><description>&lt;p&gt;主要是技术性运维总结，主打通俗易懂和快速上手，同时也是对PG数据库运维的阶段性总结，希望对PGer有所帮助。&lt;/p&gt;
&lt;p&gt;历史的运维经验：&lt;a href="https://www.modb.pro/db/1876933230968975360" target="_blank" rel="noreferrer"&gt;pg数据库运维经验2024&lt;/a&gt;。注意，本篇不会包含历史的运维经验的内容。&lt;/p&gt;

&lt;h2 class="relative group"&gt;CPU
 &lt;div id="cpu" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#cpu" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;SQL性能问题是PG异常处理根因中最多的，这包含SQL本身性能不好，索引一般、突发并发高、执行计划突变。对于postgres这种没有完善的绑定执行计划的方案的库来说，有一个DBA团队帮助设计数据模型、数据访问方式、索引、调整执行计划等显得尤为重要，实际上可以极大缓解CPU突然打满的问题。&lt;/p&gt;</description><content:encoded>&lt;p&gt;主要是技术性运维总结，主打通俗易懂和快速上手，同时也是对PG数据库运维的阶段性总结，希望对PGer有所帮助。&lt;/p&gt;
&lt;p&gt;历史的运维经验：&lt;a href="https://www.modb.pro/db/1876933230968975360" target="_blank" rel="noreferrer"&gt;pg数据库运维经验2024&lt;/a&gt;。注意，本篇不会包含历史的运维经验的内容。&lt;/p&gt;

&lt;h2 class="relative group"&gt;CPU
 &lt;div id="cpu" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#cpu" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;SQL性能问题是PG异常处理根因中最多的，这包含SQL本身性能不好，索引一般、突发并发高、执行计划突变。对于postgres这种没有完善的绑定执行计划的方案的库来说，有一个DBA团队帮助设计数据模型、数据访问方式、索引、调整执行计划等显得尤为重要，实际上可以极大缓解CPU突然打满的问题。&lt;/p&gt;

&lt;h3 class="relative group"&gt;执行计划
 &lt;div id="执行计划" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%89%a7%e8%a1%8c%e8%ae%a1%e5%88%92" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;执行计划突变是cost-base优化器的老毛病，postgres也不会例外。&lt;/p&gt;

&lt;h4 class="relative group"&gt;DISTINCT不准确
 &lt;div id="distinct不准确" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#distinct%e4%b8%8d%e5%87%86%e7%a1%ae" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://www.modb.pro/db/1976119963471589376" target="_blank" rel="noreferrer"&gt;案例-从distinct不准确到DISTINCT的计算原理&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;由于默认采样数最大是3w行，也就是说这种采样算法只要超过3w，即表比较大的时候，预估distinct很可能偏小。注意这里的数据不能有太多唯一值。&lt;/p&gt;
&lt;p&gt;测试一张表不同采样数的差异：&lt;/p&gt;
&lt;p&gt;表有reltuples=8亿，relpages=2kw，size=175GB，真实的某字段distinct 1亿&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;target statistics&lt;/th&gt;
 &lt;th&gt;pages采样比例（1）&lt;/th&gt;
 &lt;th&gt;tuples采样比例（1）&lt;/th&gt;
 &lt;th&gt;n_distinct&lt;/th&gt;
 &lt;th&gt;执行时间&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;50&lt;/td&gt;
 &lt;td&gt;0.00075&lt;/td&gt;
 &lt;td&gt;0.00001875&lt;/td&gt;
 &lt;td&gt;6w&lt;/td&gt;
 &lt;td&gt;2秒&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;100&lt;/td&gt;
 &lt;td&gt;0.0015&lt;/td&gt;
 &lt;td&gt;0.0000375&lt;/td&gt;
 &lt;td&gt;11w&lt;/td&gt;
 &lt;td&gt;5秒&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;1000&lt;/td&gt;
 &lt;td&gt;0.015&lt;/td&gt;
 &lt;td&gt;0.000375&lt;/td&gt;
 &lt;td&gt;103w&lt;/td&gt;
 &lt;td&gt;58秒&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;3000&lt;/td&gt;
 &lt;td&gt;0.045&lt;/td&gt;
 &lt;td&gt;0.001125&lt;/td&gt;
 &lt;td&gt;268w&lt;/td&gt;
 &lt;td&gt;3分01秒&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;10000&lt;/td&gt;
 &lt;td&gt;0.15&lt;/td&gt;
 &lt;td&gt;0.00375&lt;/td&gt;
 &lt;td&gt;675w&lt;/td&gt;
 &lt;td&gt;7分21秒&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;（target statistics 最大值10000）&lt;/p&gt;
&lt;p&gt;可以粗糙的总结：n_distinct和analyze的执行时间随采样数量成倍增长。&lt;/p&gt;
&lt;p&gt;n_distinct随采样数量增长，pages和tuples却一直都很准确。&lt;/p&gt;

&lt;h4 class="relative group"&gt;generic plan的干扰
 &lt;div id="generic-plan的干扰" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#generic-plan%e7%9a%84%e5%b9%b2%e6%89%b0" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;pg的执行计划要考虑generic plan。generic plan与传参是无关的，它用一些默认值计算cost，并与前五次计划的代价进行对比，谁小用谁。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.modb.pro/db/1964312913808732160" target="_blank" rel="noreferrer"&gt;案例-添加索引性能下降和generic plan&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;一、generic plan预估不准的问题分类&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;因为有5次机制对比，所以generic plan的问题可以分为2种：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;前5次SQL的执行没有普遍性。跟前5次执行计划相关性大，依赖数据倾斜和前5次参数是否具有普遍性。&lt;/li&gt;
&lt;li&gt;generic plan本身有问题。generic plan因为数据倾斜或数据均衡但无法准确计算选择率，导致generic plan本身执行效率低下&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;二、解决方案参考&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;generic plan问题在分区表上可能会出现，分区键是连续的，扫描所有分区建选择率应该为1，但generic plan为0.05，很可能导致走“全索引”扫描这种场景。&lt;/p&gt;
&lt;p&gt;所以在优化的时候需要考虑更多：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不要建太多索引迷惑优化器&lt;/li&gt;
&lt;li&gt;排除generic plan的干扰。用&lt;code&gt;EXECUTE&lt;/code&gt;真实跑6次&lt;/li&gt;
&lt;li&gt;会话级别&lt;code&gt;set plan_cache_mode='force_generic_plan'&lt;/code&gt;; or &lt;code&gt;set plan_cache_mode='force_custom_plan';&lt;/code&gt;对比执行计划；或者在pg16+用&lt;code&gt;explain (GENERIC_PLAN)&lt;/code&gt;对比执行计划&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;语法参考：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--prepare/excute
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PREPARE sql1(text) AS
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SELECT COUNT(*) FROM LZL where a=$1;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;EXECUTE sql1(&amp;#39;zzz&amp;#39;); --跑6次再说
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;EXPLAIN EXECUTE sql1(&amp;#39;zzz&amp;#39;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;select * from pg_prepared_statements --查看prepare语句信息，只能看当前会话
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--对比执行计划，设置会话参数后执行EXPLAIN EXECUTE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;set plan_cache_mode=&amp;#39;force_generic_plan&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;set plan_cache_mode=&amp;#39;force_custom_plan&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--直接查看genetic plan,16+
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;explain (GENERIC_PLAN) xx &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 class="relative group"&gt;行锁导致的LWLock:Lockmanager
 &lt;div id="行锁导致的lwlocklockmanager" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%a1%8c%e9%94%81%e5%af%bc%e8%87%b4%e7%9a%84lwlocklockmanager" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;LWLock Lockmanager问题一般发生在分区表上，高并发没有分区键的SQL容易发生。而今年又发现一个新的场景：&lt;a href="https://www.modb.pro/db/1995089823380627456" target="_blank" rel="noreferrer"&gt;行锁导致的LWLock:Lockmanager&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这不算一个很大的问题，因为更新同一行会阻塞是众所周知的。只是没有测试前我也没有想到更新同一行也会产生LWLock:Lockmanager。不算特别有价值的案例，在观察等待事件有LWLock:Lockmanager时考虑行锁即可。&lt;/p&gt;

&lt;h3 class="relative group"&gt;idle连接数
 &lt;div id="idle连接数" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#idle%e8%bf%9e%e6%8e%a5%e6%95%b0" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;PostgreSQL的性能基本随着大版本提升而稳定提升。其中PG14对快照的获取和维护所有backend的事务信息都做了&lt;a href="https://liuzhilong.blog.csdn.net/article/details/130783036" target="_blank" rel="noreferrer"&gt;大幅优化&lt;/a&gt;，使得14对多idle connection的提升明显：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/88df744da257.jpg" alt="performance-impact-of-idle-connections-48active-prepost.png" /&gt;（https://techcommunity.microsoft.com/blog/adforpostgresql/improving-postgres-connection-scalability-snapshots/1806462）&lt;/p&gt;
&lt;p&gt;但，这不代表14以后就不需要关注idle连接数了，它仍然会消耗backend事务维护成本、上下文切换、使内存碎片化等问题，导致数据库的idle连接数越多性能越差。&lt;/p&gt;
&lt;p&gt;一般业务连接本身是有轮询和保活的，保持一定的idle是为了不让每个请求都新建连接，那样消耗就大了去了。一般小库是不太需要关注连接数（只要别太离谱），因为CPU买的不多，系统也没那么重要，而且扩容比较容易。但是大库又不一样了。CPU数就是主机资源上限，再加也加不上去了。大库本身idle connection就很多，再增加空闲连接不一定会增加系统的吞吐量，特别是CPU已经不太够时，增加idle连接会起反向效果。&lt;/p&gt;
&lt;p&gt;以PG15压测经验来看，以5k idle为基线，上1w个idle时，idle的维护会多使用2-5个vCPU，上2w个idle时，多使用5-10个vCPU。大致情况是这样。&lt;/p&gt;

&lt;h3 class="relative group"&gt;idle in transaction
 &lt;div id="idle-in-transaction" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#idle-in-transaction" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;去年狠狠把长事务批判了一遍，因为长事务对PG的影响要比其他库（oracle、mysql等）要大。但这问题不大，做好告警和运维，长事务问题是可解决的。&lt;/p&gt;
&lt;p&gt;在监控会话状态时，一般都要查看会话状态，比如active代表正在运行，代表在跑SQL，idle in transaction代表事务在空闲状态，代表事务没有在跑SQL也没有提交。所有的&lt;a href="https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-ACTIVITY-VIEW" target="_blank" rel="noreferrer"&gt;pg_stat_activity.state如下，pg15&lt;/a&gt;：&lt;/p&gt;
&lt;p&gt;Current overall state of this backend. Possible values are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;active&lt;/code&gt;: The backend is executing a query.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;idle&lt;/code&gt;: The backend is waiting for a new client command.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;idle in transaction&lt;/code&gt;: The backend is in a transaction, but is not currently executing a query.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;idle in transaction (aborted)&lt;/code&gt;: This state is similar to &lt;code&gt;idle in transaction&lt;/code&gt;, except one of the statements in the transaction caused an error.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fastpath function call&lt;/code&gt;: The backend is executing a fast-path function.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;disabled&lt;/code&gt;: This state is reported if &lt;a href="https://www.postgresql.org/docs/15/runtime-config-statistics.html#GUC-TRACK-ACTIVITIES" target="_blank" rel="noreferrer"&gt;track_activities&lt;/a&gt; is disabled in this backend.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;常见的state只有&lt;code&gt;active&lt;/code&gt;,&lt;code&gt;idle&lt;/code&gt;,&lt;code&gt;idle in transaction&lt;/code&gt;,&lt;code&gt;idle in transaction (aborted)&lt;/code&gt;。&lt;code&gt;idle in transaction&lt;/code&gt;有一个误区是，它只代表当前时间没有运行sql，没有提交事务，不代表这个事务空闲了很久。不能通过事务&lt;code&gt;xact_start&lt;/code&gt; +&lt;code&gt;idle in transaction&lt;/code&gt;判断事务多久没跑，而应该通过&lt;code&gt;state_change&lt;/code&gt; +&lt;code&gt;idle in transaction&lt;/code&gt;来判断。&lt;/p&gt;

&lt;h2 class="relative group"&gt;内存
 &lt;div id="内存" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%86%85%e5%ad%98" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;内存问题非常棘手，而且今年处理了非常多，也找到了一些很好的解决方案。不过内存体系知识还是比较大，只能尽我所能尽量简化这部分知识，直达现象、结果和解决方案。&lt;/p&gt;

&lt;h3 class="relative group"&gt;内存问题和大页
 &lt;div id="内存问题和大页" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%86%85%e5%ad%98%e9%97%ae%e9%a2%98%e5%92%8c%e5%a4%a7%e9%a1%b5" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;pg内存问题分类：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/1fdf8b816eb0.png" alt="image.png" /&gt;&lt;/p&gt;
&lt;p&gt;pg内存问题相关wchan：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/c2d5d422e6f9.png" alt="image.png" /&gt;&lt;/p&gt;
&lt;p&gt;大页对内存碎片、CG内直接内存回收都非常好的效果。&lt;/p&gt;
&lt;p&gt;大页实际效果看压测：https://docs.paic.com.cn/#/post/84479375&lt;/p&gt;
&lt;p&gt;大页八股文理论效果：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;减少TLB的压力&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;减少pagetable在主内存上的大小&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;大页在物理上是连续的。连续的物理内存访问比不连续的物理内存访问更优&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;当使用大页时，page是直接映射的，不会使用多级的pte条目&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;不过使用大页会带来管理上的挑战：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;需要提前分配大页&lt;/li&gt;
&lt;li&gt;需要提前计算大页大小，以避免内存浪费&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;内存知识比较多，其他的参考&lt;a href="https://github.com/liuzhilong62/blogs/blob/main/PostgreSQL%E5%86%85%E5%8A%9F%E4%BF%AE%E7%82%BC/Linux%E5%86%85%E5%AD%98%E8%BF%9B%E9%98%B6.md" target="_blank" rel="noreferrer"&gt;Linux内存进阶&lt;/a&gt;。总之要记住如下几点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;优先排除os层问题再解决pg实例层问题&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;大页有神奇的效果，但极少数情况仍没有效果&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;很多小伙伴不会关注pgpgin/pgpgout/pgfree，甚至不会关心pgscank/pgscand，只会看cpu、内存用了多少。这对运维pg库来说是不够的。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;没有良好的运维体系pg的内存会很不稳定&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;值得注意的cgroup知识
 &lt;div id="值得注意的cgroup知识" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%80%bc%e5%be%97%e6%b3%a8%e6%84%8f%e7%9a%84cgroup%e7%9f%a5%e8%af%86" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;cgroup的知识也不少，参考之前的文章吧，这里做个简单总结。&lt;/p&gt;
&lt;p&gt;cgroup v1有自身的缺陷：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;没有统计cg pagetable&lt;/li&gt;
&lt;li&gt;没有统计cg slab&lt;/li&gt;
&lt;li&gt;没有统计cg hugepage（hugepage是没有charge，还不是没有算进去）&lt;/li&gt;
&lt;li&gt;没有统计cg异步、同步回收pages&lt;/li&gt;
&lt;li&gt;cg rss与process rss统计口径不统一&lt;/li&gt;
&lt;li&gt;shmem统计口径比较乱&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;未解之谜
 &lt;div id="未解之谜" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%9c%aa%e8%a7%a3%e4%b9%8b%e8%b0%9c" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;大页确实解决了很多问题，但不能解决所有内存问题。不能解决的这部分问题待研究，希望26年可以弄明白。&lt;/p&gt;

&lt;h2 class="relative group"&gt;关注OS
 &lt;div id="关注os" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%85%b3%e6%b3%a8os" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;关注OS的一切
 &lt;div id="关注os的一切" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%85%b3%e6%b3%a8os%e7%9a%84%e4%b8%80%e5%88%87" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;blockquote&gt;&lt;p&gt;学习开源库需要了解操作系统&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;（这句话已忘记出处）&lt;/p&gt;
&lt;p&gt;想要运维好Postgres，了解OS的原理是十分重要的。Postres数据库就是构建在OS（特别是linux）之上，linux提供什么它用什么，postgres是linux的生态。所以想要深入理解运行原理，得先了解操作系统原理。&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;优先排除os层问题再解决pg实例层问题&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;（这句话是我说的）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;一、CPU&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;因为postgres还用不了NUMA，无论是主机资源全给，还是CGROUP（or pod）管理cpu，都不太需要深入到操作系统层CPU原理。CPU问题看看SQL或者PG的堆栈基本够了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;二、内存&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;内存参考内存章节。内存问题是需要深入到OS层的。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;三、进程&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;从操作系统查看PG进程的状态非常重要，包括但不限于要查看D、wchan、RSS、SYSCALL&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;四、主机状态和日志&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;监控主机状态、包括主机层CPU、内存、IO、网络、日志。非常重要。&lt;/p&gt;
&lt;p&gt;难以想象“an I/O error occured while sending to the backend”这种网络IO的模糊告警跟底层存储是相关的。除了查看/var/log/message，pg层看不出来有什么。当然这个报错有可能不是这个原因，请勿曲解。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;五、其他&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;未归类&lt;/p&gt;

&lt;h3 class="relative group"&gt;物理读
 &lt;div id="物理读" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%89%a9%e7%90%86%e8%af%bb" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;postgres&lt;em&gt;本身不直接暴露“真正的物理磁盘读”（Physical Disk Read）指标&lt;/em&gt;。pg_stat中的各种reads（比如&lt;code&gt;pg_stat_database.blks_read&lt;/code&gt; ）都是从os cache中读。&lt;/p&gt;
&lt;p&gt;那怎么监控物理读？&lt;/p&gt;
&lt;p&gt;reads或者buffer allocation指标都是辅助策略，最好的办法还是监控OS。&lt;/p&gt;
&lt;p&gt;os是postgres的生态，绝对不要单看数据库。数据库层监控不到物理读不值得PGer shame，有方案就没问题。&lt;/p&gt;
&lt;p&gt;监控iostat以及各种五花八门的磁盘监控指标。对于云环境来说，os层的监控体系已经十分成熟了，不要浪费基于云的可观测性。&lt;/p&gt;

&lt;h2 class="relative group"&gt;autovacuum
 &lt;div id="autovacuum" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#autovacuum" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;监控autovacuum process的SQL参考&lt;a href="https://gitlab.com/postgres-ai/postgresql-consulting/postgres-howtos/-/blob/main/0067_autovacuum_queue_and_progress.md" target="_blank" rel="noreferrer"&gt;sql autovacuum_queue_and_progress&lt;/a&gt;&lt;/p&gt;

&lt;h3 class="relative group"&gt;大库的autovacuum freeze
 &lt;div id="大库的autovacuum-freeze" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%a4%a7%e5%ba%93%e7%9a%84autovacuum-freeze" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;只要把参数、监控、告警配好，autovacuum freeze在绝大部分库中，都是不太需要关注的。&lt;/p&gt;
&lt;p&gt;但是，在一些事务并发超高、数据特别大的库，仍然不可以忽略。因为autovacuum prevent wraparound可能随时都在跑，此时至少要关注如下两点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;年龄告警，及时处理并尽量避免下一次告警。不要出现快死到临头了才来着急挽救（加速方案需要看版本，比如&lt;code&gt;INDEX_CLEANUP OFF&lt;/code&gt;,&lt;code&gt;BUFFER_USAGE_LIMIT&lt;/code&gt;的调整）&lt;/li&gt;
&lt;li&gt;对内存（特别是cache）的冲击。如果autovacuum跑个不停，库又特别大，对cache也有一定冲击，对内存是有影响的&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;原理和参数参考howstos这个图：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/c216c393371f.jpg" alt="Wraparound and freeze" /&gt;&lt;/p&gt;

&lt;h3 class="relative group"&gt;大表跑不动
 &lt;div id="大表跑不动" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%a4%a7%e8%a1%a8%e8%b7%91%e4%b8%8d%e5%8a%a8" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;大表指上百GB的表，一般有许多索引和死元组才会“跑不动”。&lt;/p&gt;
&lt;p&gt;跑不动的主要原因是：(auto)vacuum会根据死元组，一条条的去索引上清理死索引元组。一般大表的(auto)vacuum就慢在这里，一般可以看到这个大表的死元组也比较多。更恐怖的是，这可能导致(auto)vacuum的运行速度慢于死元组生成速度，也就是(auto)vacuum永远跑不完，无限膨胀。&lt;/p&gt;
&lt;p&gt;对于大表跑不完的场景经验：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;同一表，死元组数&lt;em&gt;基本&lt;/em&gt;与执行时间成正比&lt;/li&gt;
&lt;li&gt;从autovacuum日志中的user time，elapsed time可以观察使用cpu时间和执行时间，即可大致推测delay sleep时间&lt;/li&gt;
&lt;li&gt;关闭autovacuum cost-based delay，可以减少3倍执行时间（与索引大小相关，属于来源：200GB表，280GB索引）&lt;/li&gt;
&lt;li&gt;调整某表的autovacuum cost-based delay含义是让autovacuum跑这个表更少的休息，会在更短的时间内消耗更多CPU以及扫描表时的io&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如何加速？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;repack。repack属于釜底抽薪型，可以快速重建表，在应急时可以使用。但repack毕竟是cli工具，每次去跑比较麻烦。&lt;/li&gt;
&lt;li&gt;调整autovacuum的 cost-based delay参数。可1.调大cost limit &lt;code&gt;alter table t1 SET (autovacuum_vacuum_cost_limit=1000);&lt;/code&gt; ,或者2.直接关闭delay睡眠时间&lt;code&gt;alter table t1 SET (autovacuum_vacuum_cost_delay=0);&lt;/code&gt;。建议仅对autovacuum跑不过来的表调整。&lt;/li&gt;
&lt;li&gt;删除不必要的索引。扫描索引并更新索引条目的时间是最久的，删除不必要的索引当然有效&lt;/li&gt;
&lt;li&gt;分区表。推荐分区大小不大于10GB；&lt;em&gt;改造为分区表是最好的方案&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;删除updated_time字段索引以利用HOT，以减少膨胀率&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;checkpoint和bgwriter
 &lt;div id="checkpoint和bgwriter" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#checkpoint%e5%92%8cbgwriter" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;checkpointer不仅要打检查点，跟实例恢复的时间相关，它还会做刷脏。而bgwriter只是做刷脏。从pg 17开始一些指标转移到&lt;code&gt;pg_stat_checkpointer&lt;/code&gt; ，这里以pg 17-为例，基本只看&lt;code&gt;pg_stat_bgwriter&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;一、checkpoint间隔&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;指标&lt;code&gt;checkpoints_timed&lt;/code&gt;：对应&lt;code&gt;checkpoint_timeout&lt;/code&gt;参数&lt;/li&gt;
&lt;li&gt;指标&lt;code&gt;checkpoints_req&lt;/code&gt;：对应&lt;code&gt;max_wal_size&lt;/code&gt;参数。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;推荐以&lt;code&gt;checkpoint_timeout&lt;/code&gt;为基本的checkpoint间隔，如果出现c&lt;code&gt;heckpoints_req&lt;/code&gt;，应该将&lt;code&gt;max_wal_size&lt;/code&gt;调大，并配合调整刷脏参数。有FPI时也应该检查这两个指标表现。&lt;/p&gt;
&lt;p&gt;二、刷脏指标&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;指标&lt;code&gt;buffers_checkpoint&lt;/code&gt;：checkpointer刷脏数&lt;/li&gt;
&lt;li&gt;指标&lt;code&gt;buffers_clean&lt;/code&gt;：bgwriter刷脏数&lt;/li&gt;
&lt;li&gt;指标&lt;code&gt;buffers_backend&lt;/code&gt;：backend刷脏数，这应该尽量少的出现，出现说明bgwriter刷脏不够激进&lt;/li&gt;
&lt;li&gt;指标&lt;code&gt;buffers_backend_fsync&lt;/code&gt;：意义不明&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;刷脏调参目标以刷脏优先级为目标，&lt;strong&gt;刷脏优先级为：bgwriter刷脏 &amp;gt; checkpointer刷脏 &amp;gt; backend刷脏&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;checkpointer虽然可以顺手刷脏，但是checkpointer不好控制刷脏速度，即可能出现checkpointer会引起IO突刺的情况。所以bgwriter的刷脏优先级应高于checkpointer。backend刷脏自不必多说，这是backend触发的刷脏，应尽量减少这种情况。&lt;/p&gt;
&lt;p&gt;三、bgwriter刷脏参数&lt;/p&gt;
&lt;p&gt;bgwriter是通过“写多少停一下然后继续写的方式”来控制刷脏速度的。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;参数&lt;code&gt;bgwriter_delay&lt;/code&gt;：停多久&lt;/li&gt;
&lt;li&gt;参数&lt;code&gt;bgwriter_lru_maxpages&lt;/code&gt;：一次最多写多少&lt;/li&gt;
&lt;li&gt;参数&lt;code&gt;bgwriter_lru_multiplier&lt;/code&gt;：一次写多少=(近期buffer allocate* lru_multiplier)，但不大于lru_maxpages&lt;/li&gt;
&lt;li&gt;参数&lt;code&gt;bgwriter_flush_after&lt;/code&gt;：刷多少后做fsync&lt;/li&gt;
&lt;li&gt;指标&lt;code&gt;pg_buffers_alloc&lt;/code&gt;：可以代表共享内存buffer的分配量。（allocate是产生了实质的换入的，可以一定程度上代表内存换入pgpgin）。&lt;/li&gt;
&lt;li&gt;指标&lt;code&gt;maxwritten_clean&lt;/code&gt;：到达&lt;code&gt;bgwriter_lru_maxpages&lt;/code&gt;的次数&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;默认的bgwriter刷脏逻辑：&lt;strong&gt;一次刷（新buffers数*2，但不大于100个dirty buffers），delay 200ms，每刷64个buffers后 fsync&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;平时的一周期刷脏量跟近期的buffer allocation多少和&lt;code&gt;bgwriter_lru_multiplier&lt;/code&gt;参数相关，而在高峰期时buffer allocation一般是比较高的，所以高峰期一般会触达&lt;code&gt;bgwriter_lru_maxpages&lt;/code&gt;上限。所以可以这样理解：&lt;strong&gt;bgwriter_lru_maxpages用于限制高峰期刷脏上限；bgwriter_lru_multiplier用于控制低峰期不要频繁刷脏&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;四、刷脏参数参考&lt;/p&gt;
&lt;p&gt;默认最大bgwriter刷脏=100*5*8k=3.9M/s。默认bgwriter刷脏参数肯定是偏小的，如果需要调大的话应该结合shared_buffer的大小和负载来进行调整。&lt;/p&gt;
&lt;p&gt;说了半天理论，实际可以参考如下调整：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#读写比2:8，负载较高&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;shared_buffers&lt;span style="color:#f92672"&gt;=&lt;/span&gt;40GB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;checkpoint_timeout&lt;span style="color:#f92672"&gt;=&lt;/span&gt;20min;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;max_wal_size&lt;span style="color:#f92672"&gt;=&lt;/span&gt;80GB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bgwriter_delay&lt;span style="color:#f92672"&gt;=&lt;/span&gt;20ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bgwriter_lru_maxpages&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bgwriter_lru_multiplier&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;看情况再进行下一步调整。&lt;/p&gt;
&lt;p&gt;至于效果，从实际的经验来看，不要期待单独调整bgwriter可以有好的效果。甚至bgwriter调整的过于激进可能会有反向效果。&lt;/p&gt;
&lt;p&gt;所以，&lt;strong&gt;你的库没有明确定位到是checkpoint刷脏突刺或者其他刷脏的问题，那就不要动这个&lt;/strong&gt;。仅推荐核心大库、并发高的库，在调整其他东西的时候（比如迁移时、调shared buffer时等）一并调整刷脏，当成附属调优策略。&lt;/p&gt;
&lt;p&gt;五、刷脏参数总结&lt;/p&gt;
&lt;p&gt;bgwriter刷脏可以总结为“三难”：&lt;/p&gt;
&lt;p&gt;“难懂、难调、难有效果”&lt;/p&gt;

&lt;h2 class="relative group"&gt;DB4AI
 &lt;div id="db4ai" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#db4ai" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;AI任务调度信息写入数据库
 &lt;div id="ai任务调度信息写入数据库" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#ai%e4%bb%bb%e5%8a%a1%e8%b0%83%e5%ba%a6%e4%bf%a1%e6%81%af%e5%86%99%e5%85%a5%e6%95%b0%e6%8d%ae%e5%ba%93" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;AI的应用已经在开发层面已经应用得非常广泛，其中一个场景是调用AI的任务会写进数据库，任务调用可能是瞬间极高的，而写入数据库的请求可能是没有并发控制的，所以会导致数据库的cpu或者其他资源使用率飙升。&lt;/p&gt;
&lt;p&gt;这是一个AI时代背景下的一个新的数据库故障场景，careful。&lt;/p&gt;

&lt;h3 class="relative group"&gt;vector hnsw
 &lt;div id="vector-hnsw" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#vector-hnsw" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;参考资料：https://postgresql.us/events/pgconfnyc2024/sessions/session/1862/slides/172/pgvector_best_practices_pgconfnyc2024.pdf&lt;/p&gt;

&lt;h4 class="relative group"&gt;HNSW索引构建加速
 &lt;div id="hnsw索引构建加速" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#hnsw%e7%b4%a2%e5%bc%95%e6%9e%84%e5%bb%ba%e5%8a%a0%e9%80%9f" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;HNSW索引在构建的时候可以非常慢，百万行数据可以慢到以小时计。&lt;/p&gt;
&lt;p&gt;影响HNSW索引构建速度的，除了套餐的内存（和cpu）以外，还有索引构建参数，例如：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;maintenance_work_mem&lt;span style="color:#f92672"&gt;=&lt;/span&gt;3g
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;max_parallel_maintenance_workers&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;m&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ef_construction&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;创建HNSW可能非常折磨人，我们可以有以下手段加速创建索引：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在数据写入前建索引，其实是一个选择。虽然initial整体时间更慢，但是开发可接受慢一点，但接收不了建1个小时的索引&lt;/li&gt;
&lt;li&gt;在数据写入后建索引优化&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SET maintenance_work_mem = '8GB'&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SET max_parallel_maintenance_workers = 8&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;after建索引需要注意内存问题，跟套餐内存，空闲内存强相关&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;注意&lt;code&gt;maintenance_work_mem &lt;/code&gt;是可以起到保护OS mem的作用，如果&lt;code&gt;maintenance_work_mem&lt;/code&gt;超过了OS mem可分配内存，且表很大，则直接报错中断连接（快速报错）&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ERROR: &lt;span style="color:#ae81ff"&gt;53200&lt;/span&gt;: could &lt;span style="color:#66d9ef"&gt;not&lt;/span&gt; resize shared memory segment &lt;span style="color:#e6db74"&gt;&amp;#34;/PostgreSQL.1390017142&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;6439348672&lt;/span&gt; bytes: Cannot &lt;span style="color:#66d9ef"&gt;allocate&lt;/span&gt; memory
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;LOCATION&lt;/span&gt;: dsm_impl_posix, dsm_impl.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;314&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;注意创建过程中使用的内存超过&lt;code&gt;maintenance_work_mem&lt;/code&gt;会有info提示（达到一定时间）&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NOTICE: &lt;span style="color:#ae81ff"&gt;00000&lt;/span&gt;: hnsw graph &lt;span style="color:#66d9ef"&gt;no&lt;/span&gt; longer fits &lt;span style="color:#66d9ef"&gt;into&lt;/span&gt; maintenance_work_mem &lt;span style="color:#66d9ef"&gt;after&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;886990&lt;/span&gt; tuples
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;DETAIL: Building will take significantly &lt;span style="color:#66d9ef"&gt;more&lt;/span&gt; time.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;HINT: Increase maintenance_work_mem &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; speed up builds.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;LOCATION&lt;/span&gt;: InsertTuple, hnswbuild.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;525&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 class="relative group"&gt;HNSW索引查询速度
 &lt;div id="hnsw索引查询速度" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#hnsw%e7%b4%a2%e5%bc%95%e6%9f%a5%e8%af%a2%e9%80%9f%e5%ba%a6" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;查询的召回率和性能之间需要做平衡，通过调整&lt;code&gt;ef_search&lt;/code&gt;参数实现。&lt;/p&gt;
&lt;p&gt;查询时除了&lt;code&gt;ef_search&lt;/code&gt;参数影响较大外，还有一个影响查询返回速度的因素：&lt;strong&gt;HNSW索引是否缓存在内中&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;索引不在内存中：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt;,buffers) &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; image_id, applyNo, feature_vector &lt;span style="color:#f92672"&gt;&amp;lt;-&amp;gt;&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; vectorsit
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; image_features_test2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ORDER&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;BY&lt;/span&gt; distance
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;LIMIT&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;----------------------------------------------------------------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Limit&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;11852&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;80&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;11865&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;74&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;35&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;82193&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;073&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;82193&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;185&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1796&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;read&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;9309&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; I&lt;span style="color:#f92672"&gt;/&lt;/span&gt;O Timings: shared&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;local&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;read&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;82108&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;559&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; InitPlan &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;returns&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Limit&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;008&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;009&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Seq Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; test_0 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;60&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1360&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;007&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;008&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_feature_hnsw &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; image_features_test2 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;11852&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;78&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;1292546&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;60&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;989705&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;35&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;82193&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;071&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;82193&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;179&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Order&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;By&lt;/span&gt;: (feature_vector &lt;span style="color:#f92672"&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1796&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;read&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;9309&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; I&lt;span style="color:#f92672"&gt;/&lt;/span&gt;O Timings: shared&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;local&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;read&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;82108&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;559&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;130&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Execution Time: &lt;span style="color:#ae81ff"&gt;82193&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;279&lt;/span&gt; ms&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;索引在内存中：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;----------------------------------------------------------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Limit&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;11852&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;80&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;11865&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;74&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;35&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;240&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;350&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;11105&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; InitPlan &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;returns&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Limit&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;007&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;008&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Seq Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; test_0 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;60&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1360&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;007&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;007&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_feature_hnsw &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; image_features_test2 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;11852&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;78&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;1292546&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;60&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;989705&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;35&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;239&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;344&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Order&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;By&lt;/span&gt;: (feature_vector &lt;span style="color:#f92672"&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;11105&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;093&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Execution Time: &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;392&lt;/span&gt; ms&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;同一个索引，同一个执行计划，&lt;strong&gt;索引是否在内存中的性能差距是82193.279/20.392=4000倍！&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这个差距是不可忽略的，关注HNSW索引性能时，一定要观测HNSW索引是否在内存中。SQL参考如下：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--buffercache查看hnsw是否在shared buffer中缓存
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;.relname, pg_size_pretty(&lt;span style="color:#66d9ef"&gt;count&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;) &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8192&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; buffered, round(&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;) &lt;span style="color:#f92672"&gt;/&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; setting &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; pg_settings &lt;span style="color:#66d9ef"&gt;WHERE&lt;/span&gt; name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;shared_buffers&amp;#39;&lt;/span&gt;)::integer, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AS&lt;/span&gt; buffer_percent, round(&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;) &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8192&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&lt;/span&gt; pg_table_size(&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;.oid), &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AS&lt;/span&gt; percent_of_relation &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; pg_class &lt;span style="color:#66d9ef"&gt;c&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;INNER&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;JOIN&lt;/span&gt; pg_buffercache b &lt;span style="color:#66d9ef"&gt;ON&lt;/span&gt; b.relfilenode &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;.relfilenode &lt;span style="color:#66d9ef"&gt;INNER&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;JOIN&lt;/span&gt; pg_database d &lt;span style="color:#66d9ef"&gt;ON&lt;/span&gt; (b.reldatabase &lt;span style="color:#f92672"&gt;=&lt;/span&gt; d.oid &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; d.datname &lt;span style="color:#f92672"&gt;=&lt;/span&gt; current_database()) &lt;span style="color:#66d9ef"&gt;GROUP&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;BY&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;.oid, &lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;.relname &lt;span style="color:#66d9ef"&gt;ORDER&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;BY&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;DESC&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;LIMIT&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; relname &lt;span style="color:#f92672"&gt;|&lt;/span&gt; buffered &lt;span style="color:#f92672"&gt;|&lt;/span&gt; buffer_percent &lt;span style="color:#f92672"&gt;|&lt;/span&gt; percent_of_relation 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;---------------------------------+------------+----------------+---------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; idx_feature_hnsw_1 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2117&lt;/span&gt; MB &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;91&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;44&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; idx_feature_hnsw &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;78&lt;/span&gt; MB &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pg_inherits_parent_index &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8192&lt;/span&gt; bytes &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 class="relative group"&gt;业务发版
 &lt;div id="业务发版" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%b8%9a%e5%8a%a1%e5%8f%91%e7%89%88" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;ddl的技巧
 &lt;div id="ddl的技巧" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#ddl%e7%9a%84%e6%8a%80%e5%b7%a7" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;online ddl工具pg-osc、pg_migrate都不支持分区表，而且工具还有一些其他问题，真实使用比较困难。所以DDL的技巧还算比较有用，可以降低锁级别、提前识别阻塞等以减少DDL阻塞和重写带来的风险。&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/5f610ac9b703.png" alt="picddl" /&gt;&lt;/p&gt;
&lt;p&gt;理解这个图的关键点：&lt;/p&gt;
&lt;p&gt;变更前的注意事项：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;确保表上没有长事务——长事务会长期持有表上的锁，长事务在pg中是危害这是共识，应先处理长事务&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;确保表上没有autovacuum (to prevent wraparound)——autovacuum一般不会阻塞SQL，但做&lt;code&gt;to prevent wraparound&lt;/code&gt;的&lt;a href="https://www.postgresql.org/docs/18/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND" target="_blank" rel="noreferrer"&gt;除外&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Autovacuum workers generally don&amp;rsquo;t block other commands. If a process attempts to acquire a lock that conflicts with the &lt;code&gt;SHARE UPDATE EXCLUSIVE&lt;/code&gt; lock held by autovacuum, lock acquisition will interrupt the autovacuum. However, if the autovacuum is running to prevent transaction ID wraparound (i.e., the autovacuum query name in the &lt;code&gt;pg_stat_activity&lt;/code&gt; view ends with &lt;code&gt;(to prevent wraparound)&lt;/code&gt;), the autovacuum is not automatically interrupted.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;lock_timeout=2000&lt;/code&gt;——即拿不到锁超过2s就不拿了，以免引发大面积阻塞&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;字段小改大的特例：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;字段小改大一般不会重写表，但有几个例外。特别要注意int-&amp;gt;bigint（常见主键字段）, char(n)-&amp;gt;char(m)）&lt;/li&gt;
&lt;li&gt;分区表索引。分区表字段小改大不会重写表，但会重建索引，而分区表重建索引一般都非常慢，很可能造成长期8级锁阻塞。这个特性是普通表没有的。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;修改字段类型：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;基本都会重写表，除了一些类型等价，或者属于另一种小改大的&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;DDL降低锁级别的注意点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;索引用CIC，分区不支持就子表CIC（记得attach index）&lt;/li&gt;
&lt;li&gt;CIC执行分了好几个阶段。其中2、3阶段会获取share锁，阻塞dml（官方文档只说了SHARE UPDATE EXCL.（不等DML），CIC不是单纯的显式锁）&lt;/li&gt;
&lt;li&gt;添加主键用using index，分区不支持就利用“子表加主键+父表添加主键可合并已存在的子表主键的特性”&lt;/li&gt;
&lt;li&gt;约束用validate constraint&lt;/li&gt;
&lt;li&gt;17以前不支持not null validate，可以用check(col1 IS NOT NULL)。这个check转not null也不会产生多余的扫描&lt;/li&gt;
&lt;li&gt;加字段有default易失会重写，可以用非易失不重写特性先加字段，不会重写。存量数据看情况update&lt;/li&gt;
&lt;li&gt;分区表attach时可以利用check约束减少停机时间，而添加check约束又可以用到validate constraint&lt;/li&gt;
&lt;li&gt;create table like+attach比partition of的锁低很多（但我还是喜欢parition of）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;变更后的注意事项：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;记得收集统计信息（很多场景需要）&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;并发创建索引
 &lt;div id="并发创建索引" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%b9%b6%e5%8f%91%e5%88%9b%e5%bb%ba%e7%b4%a2%e5%bc%95" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;在生产运维时，可能会碰到需要创建索引，但表又特别大，创建时间很长的情况。并发创建索引可以缩短建索引的时间。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;普通表并发建索引：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;并行参数：&lt;code&gt;max_parallel_maintenance_workers&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;前提：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;worker是够的，需要检查&lt;code&gt;max_parallel_workers&lt;/code&gt;,&lt;code&gt;max_worker_processes&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;调整&lt;code&gt;maintenance_work_mem&lt;/code&gt; 上GB&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;注意事项：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对 B-tree or BRIN有效&lt;/li&gt;
&lt;li&gt;&lt;code&gt;maintenance_work_mem&lt;/code&gt; limit to entire utility command。跟parallel query不同，parallel query的资源限制是 per worker process&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;从测试结果来看，并发建索引在8个并发以后收益不明显（这个结论在不同环境可能不保真）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;分区表并发建索引：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;推荐分区子表手搓并发，即一次在多个分区上创建，而不是使用原生并发，这可以减少多进程交互代价。&lt;/p&gt;

&lt;h3 class="relative group"&gt;cached plan must not change resource
 &lt;div id="cached-plan-must-not-change-resource" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#cached-plan-must-not-change-resource" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;业务前晚新增字段后，早上业务连接报错：&amp;ldquo;cached plan must not change result type in PostgreSQL&amp;rdquo;&lt;/p&gt;
&lt;p&gt;复现：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; a(b varchar(&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;PREPARE&lt;/span&gt; p1 (varchar) &lt;span style="color:#66d9ef"&gt;AS&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; a &lt;span style="color:#66d9ef"&gt;WHERE&lt;/span&gt; b&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;ALTER&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;TABLE&lt;/span&gt; a &lt;span style="color:#66d9ef"&gt;ALTER&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;COLUMN&lt;/span&gt; b &lt;span style="color:#66d9ef"&gt;TYPE&lt;/span&gt; varchar(&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;EXECUTE&lt;/span&gt; p1 (&lt;span style="color:#e6db74"&gt;&amp;#39;abcd&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ERROR: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;A000: cached plan must &lt;span style="color:#66d9ef"&gt;not&lt;/span&gt; change &lt;span style="color:#66d9ef"&gt;result&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;type&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;LOCATION&lt;/span&gt;: RevalidateCachedQuery, plancache.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;718&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;测试环境的解决办法：&lt;/strong&gt;
&lt;code&gt;DEALLOCATE ALL&lt;/code&gt;主动丢弃prepared statement
或者，
&lt;code&gt;DISCARD ALL&lt;/code&gt;主动丢弃整个会话状态&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;DEALLOCATE&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ALL&lt;/span&gt;; &lt;span style="color:#75715e"&gt;--DISCARD ALL
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;PREPARE&lt;/span&gt; p1 (varchar) &lt;span style="color:#66d9ef"&gt;AS&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; a &lt;span style="color:#66d9ef"&gt;WHERE&lt;/span&gt; b&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;EXECUTE&lt;/span&gt; p1 (&lt;span style="color:#e6db74"&gt;&amp;#39;abcd&amp;#39;&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;生产环境的解决办法：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;由于是业务层报错，JDBC可识别&lt;code&gt;DEALLOCATE ALL&lt;/code&gt;,&lt;code&gt;DISCARD ALL&lt;/code&gt;，但是业务可能没有做过。当下生产可执行如下方案：&lt;/p&gt;
&lt;p&gt;解决办法（四选一）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;由于hikari等连接池的轮询启用连接和轮询timeout机制，可kill idle会话，报错会逐渐减少&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;同样是由于连接池的轮询启用连接和轮询timeout机制，可什么都不做，等连接池逐渐建立和启用新的连接&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;如果业务压力足够大，可考虑kill所有业务连接&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;轮询重启业务&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;不&lt;/em&gt;推荐：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DDL后重启应用。有效，但不要建议“所有DDL后都应该重启应用”这样的方案&lt;/li&gt;
&lt;li&gt;&lt;code&gt;autosave=conservative&lt;/code&gt;。有效，但会启用子事务。savepoint is set for each query, however the rollback is done only for rare cases like ‘cached statement cannot change return type’ or ‘statement XXX is not valid’ so JDBC driver rolls back and retries&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;jdbc配置建议：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;配置jdbc事务回滚后自动重试：&lt;a href="https://developer.aliyun.com/article/741750" target="_blank" rel="noreferrer"&gt;https://developer.aliyun.com/article/741750&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;其他jdbc配置参考：&lt;a href="https://jdbc.postgresql.org/documentation/server-prepare/#corner-cases" target="_blank" rel="noreferrer"&gt;https://jdbc.postgresql.org/documentation/server-prepare/#corner-cases&lt;/a&gt;，注意有些建议是不能上生产的。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;物理复制
 &lt;div id="物理复制" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%89%a9%e7%90%86%e5%a4%8d%e5%88%b6" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;查询冲突
 &lt;div id="查询冲突" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%9f%a5%e8%af%a2%e5%86%b2%e7%aa%81" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;查询冲突是一个非常坑的特性，它直接影响了PG从库的查询是不那么好用的。查询冲突会导致从库延迟增加，而从库的拉数SQL本身要跑一段时间是符合逻辑的，这就导致PG管理者不得不在延迟管理和长SQL管理中做出平衡。而这个特性在其他关系型数据库中是不存在的。&lt;/p&gt;
&lt;p&gt;查询冲突要注意的隐蔽特性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;静态表同样会产生查询冲突&lt;a href="https://www.modb.pro/db/1966415366276526080" target="_blank" rel="noreferrer"&gt;（见-从静态表查询冲突到其原理）&lt;/a&gt;，也就是说冲突是快照冲突，与查询的表本身的锁几乎没有关系，快照冲突是跨表的。&lt;/li&gt;
&lt;li&gt;长查影响短查。长查把从库延迟推到&lt;code&gt;max_standby_streaming_delay&lt;/code&gt;后，此时的短查也会被掐断。&lt;/li&gt;
&lt;li&gt;不停的短查也会引起查询冲突。例如上个短查还没有结束，下一个短查又开始了，这两个短查逻辑可能是类似的，此时startup进程还没有来得应用日志。这在跑批中比较常见。这两个短查都持有那个需要应用的xid，可以检查&lt;code&gt;pg_stat_activity.backend_xmin&lt;/code&gt;是否小于startup正在应用的xid&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;查询从库推荐的实践：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;通过RTO SLO来调整&lt;code&gt;max_standby_streaming_delay&lt;/code&gt;是一个不错的选择。当吵架到没有结果时，使用SLO来进行IT管理会救命。&lt;/li&gt;
&lt;li&gt;短平快的业务查询与抽数、报表等长查询应该分到不同的从库，减少相互影响&lt;/li&gt;
&lt;li&gt;从库查询SQL也是需要优化的&lt;/li&gt;
&lt;li&gt;从库的日志应用延迟是需要监控的&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;逻辑复制
 &lt;div id="逻辑复制" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%80%bb%e8%be%91%e5%a4%8d%e5%88%b6" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;逻辑复制的坑可以说非常多了。24年有很多非常坑的案例，25年也遇到一些案例，但不算特别坑，而且主要是一些低版本pg上出现的，总体来看高版本的pg逻辑复制倾向稳定。&lt;/p&gt;

&lt;h3 class="relative group"&gt;低版本PG+DDL/DCL语句解析较慢
 &lt;div id="低版本pgddldcl语句解析较慢" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%bd%8e%e7%89%88%e6%9c%acpgddldcl%e8%af%ad%e5%8f%a5%e8%a7%a3%e6%9e%90%e8%be%83%e6%85%a2" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://www.modb.pro/db/1922232196358746112" target="_blank" rel="noreferrer"&gt;案例-授权和walsender跑不动&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;PG13及之前的版本，对某些DDL、DCL语句解析较慢，可能会影响walsender延迟。这些DDL、DCL包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;批量授权（含grant all tables）+ 安装了pathman extension（无论是否使用）&lt;/li&gt;
&lt;li&gt;批量DDL/TRUNCATE/DCL/DROP PUBLICATION&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;低版本PG+多链路重复解析+flink
 &lt;div id="低版本pg多链路重复解析flink" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%bd%8e%e7%89%88%e6%9c%acpg%e5%a4%9a%e9%93%be%e8%b7%af%e9%87%8d%e5%a4%8d%e8%a7%a3%e6%9e%90flink" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;flink只能一个表一条链路，加上pg的walsender是重复解析的，一个pg库上几十条flink链路的walsender都是常见情况，而且改造困难。&lt;/p&gt;
&lt;p&gt;而在pg11及以前，在walsender主循环中有&lt;code&gt;PostmasterIsAlive()&lt;/code&gt;函数，导致主循环性能较差。从pg12开始&lt;code&gt;WalSndLoop&lt;/code&gt;函数没有在主循环中频繁轮询&lt;code&gt;PostmasterIsAlive()&lt;/code&gt;，而是将状态检查放到&lt;code&gt;WalSndWait&lt;/code&gt;中，通过事件机制被动等待通知。这极大的缓解了CPU的争用。&lt;/p&gt;
&lt;p&gt;如果库中有多个flink链路，而且pg版本较低，建议升级版本，可以缓解一定的walsender资源争用问题。这些可以缓解的资源问题包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可能会解决walsender启动时资源争用导致数据库长时间起不来的问题&lt;/li&gt;
&lt;li&gt;可能会解决上游大量数据变动（含DDL重写）导致runtime walsender解析日志的cpu打满问题&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;低版本PG无法自动同步新分区
 &lt;div id="低版本pg无法自动同步新分区" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%bd%8e%e7%89%88%e6%9c%acpg%e6%97%a0%e6%b3%95%e8%87%aa%e5%8a%a8%e5%90%8c%e6%ad%a5%e6%96%b0%e5%88%86%e5%8c%ba" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;PG声明式分区在低版本需要注意&lt;em&gt;仅&lt;/em&gt;能通过子表发布。&lt;a href="https://www.postgresql.org/docs/release/13.0/" target="_blank" rel="noreferrer"&gt;pg版本&amp;gt;=13才支持按照父表配置发布&lt;/a&gt;，低于这个版本只能按分区子表的名称配置同步：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Allow partitioned tables to be logically replicated via &lt;a href="https://www.postgresql.org/docs/13/sql-createpublication.html" target="_blank" rel="noreferrer"&gt;publications&lt;/a&gt; (Amit Langote) &lt;a href="https://postgr.es/c/17b9e7f9f" target="_blank" rel="noreferrer"&gt;§&lt;/a&gt; &lt;a href="https://postgr.es/c/83fd4532a" target="_blank" rel="noreferrer"&gt;§&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Previously, partitions had to be replicated individually. Now a partitioned table can be published explicitly, causing all its partitions to be published automatically. Addition/removal of a partition causes it to be likewise added to or removed from the publication. The &lt;a href="https://www.postgresql.org/docs/13/sql-createpublication.html" target="_blank" rel="noreferrer"&gt;&lt;code&gt;CREATE PUBLICATION&lt;/code&gt;&lt;/a&gt; option &lt;code&gt;publish_via_partition_root&lt;/code&gt; controls whether changes to partitions are published as their own changes or their parent&amp;rsquo;s.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;也就是说，这个分区表如果是同步上游，每新增分区时，都要适配同步工具做发布，不然无法同步新分区数据。&lt;/p&gt;

&lt;h2 class="relative group"&gt;迁移和升级
 &lt;div id="迁移和升级" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%bf%81%e7%a7%bb%e5%92%8c%e5%8d%87%e7%ba%a7" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;迁移信创和glibc升级
 &lt;div id="迁移信创和glibc升级" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%bf%81%e7%a7%bb%e4%bf%a1%e5%88%9b%e5%92%8cglibc%e5%8d%87%e7%ba%a7" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;无论是信创迁移还是LINUX OS版本升级，都可能涉及glibc的升级，而glibc升级可能会非常坑。pg的排序在17以前都是完全依赖操作系统的。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;pg没有办法检测glibc升级带来的兼容性问题&lt;/strong&gt;。GNU C library每个小版本都会对locale做出改动，现实中最容易出问题的版本是&lt;strong&gt;glibc 2.28&lt;/strong&gt;，因为2.28升级了大版本&lt;strong&gt;unicode 9.0.0&lt;/strong&gt;(&lt;a href="https://sourceware.org/glibc/wiki/Release/2.28" target="_blank" rel="noreferrer"&gt;has been updated to a new upstream version from ISO which is in sync with Unicode 9.0.0&lt;/a&gt;)。&lt;/p&gt;
&lt;p&gt;排序规则分了很多种，而很多环境用的是语义排序（例如en_US.utf8），语义排序也是最吃版本的。排序规则变化最常见的是引起查询索引时数据库奔溃，也还有其他不常见问题比如重复主键、分区表数据存入错误分区、merge join结果返回不一致等等。&lt;/p&gt;
&lt;p&gt;好在pg17提供了非常安全的locale提供方式：builtin，不再依赖OS提供的glibc、ICU等provider。启用命令例如：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;initdb --locale-provider&lt;span style="color:#f92672"&gt;=&lt;/span&gt;builtin --bultin-locale&lt;span style="color:#f92672"&gt;=&lt;/span&gt;C.UTF-8 dbname1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;但是，&lt;/p&gt;
&lt;p&gt;builtin虽然是个好东西但是来得太迟了。大量已投入使用的数据库实例，想转builtin的字符集可不是一件容易的事。而且，信创迁移或者OS升级可能不会将数据库升级作为强制动作。&lt;/p&gt;
&lt;p&gt;信创迁移时，信创主机的glibc版本一般都比老的英特尔服务器glibc版本高，很可能跨了2.28这个版本。加上任务急、kpi推动、人力不足和大库，物理迁移是在所难免。所以信创物理迁移得关注glibc版本和collation导致的许多异常。&lt;/p&gt;
&lt;p&gt;物理迁移后可以做什么？&lt;/p&gt;
&lt;p&gt;一、官方必修方案&lt;/p&gt;
&lt;p&gt;1.check索引，重建明显有问题的索引&lt;/p&gt;
&lt;p&gt;2.REFRESH DATABASE COLLATION VERSION&lt;/p&gt;
&lt;p&gt;3.检查依赖对象&lt;/p&gt;
&lt;p&gt;4.REFRESH COLLATION VERSION&lt;/p&gt;
&lt;p&gt;二、非官方邪修方案&lt;/p&gt;
&lt;p&gt;我这没有做出完整的方案，只是一点思路。&lt;/p&gt;
&lt;p&gt;1.处理分区表写入错误分区的问题&lt;/p&gt;
&lt;p&gt;分区键是int/bigint/float，跟collation没有关系，可以不用管了&lt;/p&gt;
&lt;p&gt;分区键是时间分区，如果是timestamp不用管了，如果是varchar等等字符类型，就看情况了&lt;/p&gt;
&lt;p&gt;分区键是字符类型，参考“a”和“-”的排序（pgconf Collation Challenges Sorting It Out）。但要注意以下几点&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如果要查数据的话，不要从父表查，可能会崩或者查不出来&lt;/li&gt;
&lt;li&gt;没有简单的检测方案&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;2.处理主键/唯一键冲突&lt;/p&gt;
&lt;p&gt;3.处理fdw排序范围异常的问题&lt;/p&gt;
&lt;p&gt;4.未知问题&lt;/p&gt;
&lt;p&gt;参考&lt;a href="https://docs.paic.com.cn/#/post/122695260" target="_blank" rel="noreferrer"&gt;collation&lt;/a&gt;&lt;/p&gt;

&lt;h3 class="relative group"&gt;丝滑大版本升级
 &lt;div id="丝滑大版本升级" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%b8%9d%e6%bb%91%e5%a4%a7%e7%89%88%e6%9c%ac%e5%8d%87%e7%ba%a7" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://gitlab.com/postgres-ai/postgresql-consulting/postgres-howtos/-/blob/main/0077_zero_downtime_major_upgrade.md?ref_type=heads" target="_blank" rel="noreferrer"&gt;https://gitlab.com/postgres-ai/postgresql-consulting/postgres-howtos/-/blob/main/0077_zero_downtime_major_upgrade.md?ref_type=heads&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.postgresql.eu/events/pgconfeu2023/sessions/session/4791/slides/439/2023.pgconf.eu%20Zero%20Downtime%20PostgreSQL%20Upgrades.pdf" target="_blank" rel="noreferrer"&gt;https://www.postgresql.eu/events/pgconfeu2023/sessions/session/4791/slides/439/2023.pgconf.eu%20Zero%20Downtime%20PostgreSQL%20Upgrades.pdf&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;一般的大版本升级方案：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pg_upgrade原地升级。不推荐，可能原地爆炸。&lt;/li&gt;
&lt;li&gt;pgdump：适合小库，窗口期较长的库&lt;/li&gt;
&lt;li&gt;逻辑同步+switchover（发布订阅/pg_logical/dts等）：适合小库，窗口期较短的库&lt;/li&gt;
&lt;li&gt;物理正向同步+逻辑反向同步：适合大库，窗口期不太长的库&lt;/li&gt;
&lt;li&gt;物理复制全量+逻辑同步增量+switchover：适合大库，窗口期极短的库&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;用逻辑同步同步全量数据可能是非常慢的，而用新从库原地升级本身带有不确定性，有一定的升级时间，而且也要解决反向逻辑同步的问题。“丝滑大版本升级”其实就是“物理复制全量+逻辑同步增量+switchover”。&lt;/p&gt;
&lt;p&gt;丝滑大版本升级的主要技术：主库创建slot会返回LSN，新从库&lt;code&gt;recovery_target_lsn&lt;/code&gt; 恢复到这个LSN，然后开启逻辑同步。&lt;/p&gt;
&lt;p&gt;方案的大致流程：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;预检查。多db（多db要考虑应用一个slot lsn）、插件、pathman、trigger、外键、unlogged表、crontab等等&lt;/li&gt;
&lt;li&gt;物理同步。新老版本软件、对比和备份conf文件、pg_basebackup搭建低版本新库&lt;/li&gt;
&lt;li&gt;逻辑同步准备一。主键和复制标识、创建发布；禁止业务发布DDL/DCL&lt;/li&gt;
&lt;li&gt;新库恢复到target LSN。停新库；老库创建slot并记录LSN；新库以target LSN启动&lt;/li&gt;
&lt;li&gt;新库大版本升级。升级、处理各种问题、环境变量切换&lt;/li&gt;
&lt;li&gt;逻辑同步准备二。禁用trigger、外键、任务、插件等&lt;/li&gt;
&lt;li&gt;逻辑同步。创建指定slot的copy_data=false订阅&lt;/li&gt;
&lt;li&gt;逻辑同步后。索引损坏检查、检查日志报错并修复、重建同城远程&lt;/li&gt;
&lt;li&gt;switchover。停业务；提升序列、启用外键、trigger、任务等&lt;/li&gt;
&lt;li&gt;switchover。搭建反向链路（老库订阅）&lt;/li&gt;
&lt;li&gt;switchover。业务切换&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;丝滑大版本升级的方案对于业务很丝滑，对于DBA很复杂。这个方案包含了逻辑迁移和物理迁移的所有缺点，做起来是比较痛苦的，以上步骤已经简化过了。该方案消耗DBA人力，对于非常重要的库可以考虑这个方案。&lt;/p&gt;

&lt;h2 class="relative group"&gt;分区表的管理
 &lt;div id="分区表的管理" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%88%86%e5%8c%ba%e8%a1%a8%e7%9a%84%e7%ae%a1%e7%90%86" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Postgres分区表非常灵活，没有自增interval分区功能，而且版本多变，导致分区表运维管理问题几乎是年年发生。我相信有不少PG DBA对于新分区的各种问题还提心吊胆的。&lt;/p&gt;
&lt;p&gt;我自己观察下来分区表的管理和使用主要有如下问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;未使用声明式分区表&lt;/strong&gt;。老版本仍然使用pathman分区或继承表分区，或者即便升级后仍然使用pathman分区或继承表分区。PG10开始支持声明式分区，由于早期版本有功能不足，建议至少PG12以后就&lt;em&gt;仅&lt;/em&gt;使用声明式分区表，以减少环境的复杂性。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;开发自建子表索引/主键&lt;/strong&gt;。不通过父表默认继承而是通过SQL直接在子表建索引/主键，会导致下一次开发写SQL时可能就忘记了。这不仅会导致父子不一致，也会导致子子不一致，最终导致分区表结构面目全非。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;新分区无管理策略&lt;/strong&gt;。忘记建新分区或者用default分区。一般开发会建个几年的分区，下一次可能开发都换了一批了，没人会去管这个新分区建设。这会定时炸弹随时爆炸，或者数据写入default分区失去分区意义。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;缺乏DBA的管理&lt;/strong&gt;。是的，DBA！PG的分区表知识实在是多（参考&lt;a href="https://blog.csdn.net/qq_40687433/article/details/132525655?spm=1001.2014.3001.5501" target="_blank" rel="noreferrer"&gt;PostgreSQL分区表&lt;/a&gt;），怎么基于自己的环境做管理策略和落地，需要专业DBA的主动推动。这可能是最重要的。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;自己思考的分区表管理目标（copy的这个&lt;a href="https://www.modb.pro/db/2007743085057499136" target="_blank" rel="noreferrer"&gt;案例-20260101分区数据更新失败&lt;/a&gt;）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;以主表结构为标准结构，即主表面向开发，它上面应该有主键、索引、复制标识（pg版本不支持除外）&lt;/li&gt;
&lt;li&gt;主表与子表保持一致，使用partition of创建新分区（是的，我不推荐attach）&lt;/li&gt;
&lt;li&gt;子表与子表保持一致&lt;/li&gt;
&lt;li&gt;提前创建新分区，分区数据量不宜过多&lt;/li&gt;
&lt;li&gt;default分区不建议创建，如果创建必须监控其写入情况&lt;/li&gt;
&lt;li&gt;频繁访问的表的SQL必须包含分区键，使用分区裁剪，不然改造为普通表&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;可观测性
 &lt;div id="可观测性" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%8f%af%e8%a7%82%e6%b5%8b%e6%80%a7" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;从&lt;a href="https://www.postgresql.org/docs/18/monitoring-stats.html" target="_blank" rel="noreferrer"&gt;官方文档&lt;/a&gt;中基本都能看到数据库、表、索引、SQL、刷脏等等指标释义，还是比较清楚的。&lt;/p&gt;
&lt;p&gt;其中有几个指标可能要特别注意一下，不仅解释的不是很清楚，而且常用且有理解成本。&lt;/p&gt;

&lt;h3 class="relative group"&gt;buffers_alloc、blks_read
 &lt;div id="buffers_allocblks_read" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#buffers_allocblks_read" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pg_stat_bgwriter.buffers_alloc&lt;/code&gt;： Number of buffers allocated，共享内存置换量&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pg_stat_database.blks_read&lt;/code&gt; ：os cache读&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;（&lt;code&gt;buffers_alloc&lt;/code&gt;在不同PG版本可能在不同视图中，但含义不变）&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pg_stat_bgwriter.buffers_alloc&lt;/code&gt;是共享内存的buffer分配量，源码中叫buffer allocation。可以代表共享内存的置换量，新起的库一般这个值比较高。观察共享内存繁忙程度时，buffer allocate可能要比命中率好，命中率高可能就是小表频繁访问拉高了，allocate是产生了实质的置换的。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;buffers_alloc&lt;/code&gt;是从cache读数后加载到新的共享内存buffer，其实也能一定程度代表os cache read吧？但是实际观察下来，&lt;code&gt;buffers_alloc&lt;/code&gt;与&lt;code&gt;blks_read&lt;/code&gt;含义如此相似但数值可能差异较大。为什么？没搞懂，待研究。&lt;/p&gt;
&lt;p&gt;源码：&lt;code&gt;numBufferAllocs&lt;/code&gt;&lt;/p&gt;

&lt;h3 class="relative group"&gt;tup_fetched、tup_returned
 &lt;div id="tup_fetchedtup_returned" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#tup_fetchedtup_returned" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;这俩是&lt;code&gt;pg_stat_database&lt;/code&gt; 中的指标：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tup_fetched&lt;/code&gt; ：索引扫描最终获取的行数，去掉了过滤条件、死亡元组、不可见行后的行。偏向于结果。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tup_returned&lt;/code&gt; ：索引扫描回表的行数，不管是否满足过滤条件、死亡元组、不可见行后的行。偏向于处理过程&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以，&lt;code&gt;tup_returned&lt;/code&gt; 一般比&lt;code&gt;tup_fetched&lt;/code&gt; 高不少。而异常高，也代表可能有优化空间，因为毕竟访问了这么多数据，实际上没有返回给客户端多少。&lt;/p&gt;

&lt;h3 class="relative group"&gt;idx_tup_fetch 、idx_tup_read
 &lt;div id="idx_tup_fetch-idx_tup_read" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#idx_tup_fetch-idx_tup_read" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;这俩是&lt;code&gt;pg_stat_all_indexes&lt;/code&gt; 中的指标：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;idx_tup_read&lt;/code&gt; ：从索引计数的访问索引条目数，包含bitmap scan&lt;/li&gt;
&lt;li&gt;&lt;code&gt;idx_tup_fetch&lt;/code&gt; ：从表计数的索引扫描最终返回的行数，不包含bitmap scan&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;疯了&lt;/p&gt;
&lt;p&gt;可以记住一个点：&lt;code&gt;xx_tup_fetch&lt;/code&gt;&lt;strong&gt;是指经过索引回表访问后返回的最终行数，偏向于结果。&lt;/strong&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;参考内容
 &lt;div id="参考内容" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%8f%82%e8%80%83%e5%86%85%e5%ae%b9" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://gitlab.com/postgres-ai/postgresql-consulting/postgres-howtos" target="_blank" rel="noreferrer"&gt;postgres-ai howtos&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://postgresql.us/events/pgconfnyc2024/sessions/session/1862/slides/172/pgvector_best_practices_pgconfnyc2024.pdf" target="_blank" rel="noreferrer"&gt;Best practices for using pgvector&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.modb.pro/db/2007743085057499136" target="_blank" rel="noreferrer"&gt;案例-20260101分区数据更新失败&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.csdn.net/qq_40687433/article/details/132525655?spm=1001.2014.3001.5501" target="_blank" rel="noreferrer"&gt;PostgreSQL分区表&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.modb.pro/db/1976119963471589376" target="_blank" rel="noreferrer"&gt;案例-从distinct不准确到DISTINCT的计算原理&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.modb.pro/db/1964312913808732160" target="_blank" rel="noreferrer"&gt;案例-添加索引性能下降和generic plan&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.modb.pro/db/1966415366276526080" target="_blank" rel="noreferrer"&gt;从静态表查询冲突到其原理&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.modb.pro/db/1948643346948304896" target="_blank" rel="noreferrer"&gt;控制文件上的参数和主从参数不一致问题&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://liuzhilong.blog.csdn.net/article/details/130783036" target="_blank" rel="noreferrer"&gt;https://liuzhilong.blog.csdn.net/article/details/130783036&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://techcommunity.microsoft.com/blog/adforpostgresql/improving-postgres-connection-scalability-snapshots/1806462" target="_blank" rel="noreferrer"&gt;https://techcommunity.microsoft.com/blog/adforpostgresql/improving-postgres-connection-scalability-snapshots/1806462&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.postgresql.org/docs/17/sql-prepare.html" target="_blank" rel="noreferrer"&gt;https://www.postgresql.org/docs/17/sql-prepare.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.postgresql.org/docs/17/sql-deallocate.html" target="_blank" rel="noreferrer"&gt;https://www.postgresql.org/docs/17/sql-deallocate.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.postgresql.org/docs/release/13.0/" target="_blank" rel="noreferrer"&gt;https://www.postgresql.org/docs/release/13.0/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://jdbc.postgresql.org/documentation/use/" target="_blank" rel="noreferrer"&gt;https://jdbc.postgresql.org/documentation/use/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://jdbc.postgresql.org/documentation/server-prepare/#server-prepared-statements" target="_blank" rel="noreferrer"&gt;https://jdbc.postgresql.org/documentation/server-prepare/#server-prepared-statements&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.postgresql.eu/events/pgconfeu2023/sessions/session/4791/slides/439/2023.pgconf.eu%20Zero%20Downtime%20PostgreSQL%20Upgrades.pdf" target="_blank" rel="noreferrer"&gt;https://www.postgresql.eu/events/pgconfeu2023/sessions/session/4791/slides/439/2023.pgconf.eu%20Zero%20Downtime%20PostgreSQL%20Upgrades.pdf&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;感谢25年跟高大师的battle&lt;/p&gt;</content:encoded></item><item><title>案例-20260101分区数据更新失败</title><link>https://lastdba.com/2026/01/04/%E6%A1%88%E4%BE%8B-20260101%E5%88%86%E5%8C%BA%E6%95%B0%E6%8D%AE%E6%9B%B4%E6%96%B0%E5%A4%B1%E8%B4%A5/</link><pubDate>Sun, 04 Jan 2026 00:00:00 +0000</pubDate><guid>https://lastdba.com/2026/01/04/%E6%A1%88%E4%BE%8B-20260101%E5%88%86%E5%8C%BA%E6%95%B0%E6%8D%AE%E6%9B%B4%E6%96%B0%E5%A4%B1%E8%B4%A5/</guid><description>&lt;h2 class="relative group"&gt;现象
 &lt;div id="现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;12月30日发现业务报错，数据无法更新：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ERROR: &lt;span style="color:#ae81ff"&gt;55000&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; cannot update table &lt;span style="color:#e6db74"&gt;&amp;#34;tablzl_202601&amp;#34;&lt;/span&gt; because it does not have a replica identity and publishes updates
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;HINT: To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;LOCATION: CheckCmdReplicaIdentity, execReplication.c:&lt;span style="color:#ae81ff"&gt;575&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 class="relative group"&gt;临时恢复
 &lt;div id="临时恢复" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%b8%b4%e6%97%b6%e6%81%a2%e5%a4%8d" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;因为报错信息充足，没有复制标识，表是一个分区表，又是26年的分区，所以直接怀疑新分区没有主键（新表的复制标识是default，default只能用主键作为复制标识，没有主键就会无法更新）。&lt;/p&gt;</description><content:encoded>
&lt;h2 class="relative group"&gt;现象
 &lt;div id="现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;12月30日发现业务报错，数据无法更新：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ERROR: &lt;span style="color:#ae81ff"&gt;55000&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; cannot update table &lt;span style="color:#e6db74"&gt;&amp;#34;tablzl_202601&amp;#34;&lt;/span&gt; because it does not have a replica identity and publishes updates
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;HINT: To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;LOCATION: CheckCmdReplicaIdentity, execReplication.c:&lt;span style="color:#ae81ff"&gt;575&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 class="relative group"&gt;临时恢复
 &lt;div id="临时恢复" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%b8%b4%e6%97%b6%e6%81%a2%e5%a4%8d" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;因为报错信息充足，没有复制标识，表是一个分区表，又是26年的分区，所以直接怀疑新分区没有主键（新表的复制标识是default，default只能用主键作为复制标识，没有主键就会无法更新）。&lt;/p&gt;
&lt;p&gt;然后发现，父表没有任何主键和索引，25年以前的老子分区有主键和索引，26年以后的新子分区没有任何主键和索引，且所有子分区有发布。大概如下：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;p_parent &lt;span style="color:#75715e"&gt;--无主键无索引
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;p_child_202511 &lt;span style="color:#75715e"&gt;--有主键有索引，有发布
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;p_child_202512 &lt;span style="color:#75715e"&gt;--有主键有索引，有发布
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;p_child_202601 &lt;span style="color:#75715e"&gt;--无主键无索引，有发布
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;p_child_202602 &lt;span style="color:#75715e"&gt;--无主键无索引，有发布&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;因为父表什么都没有，所以partition of添加子分区也会什么都没有，只有自己准备子分区的主键和索引，所以推测新分区创建的有问题，老分区新建时应该是处理过的。&lt;/p&gt;
&lt;p&gt;另外，通过父表发布分区表是&lt;a href="https://www.postgresql.org/docs/release/13.0/" target="_blank" rel="noreferrer"&gt;PG13才开始支持&lt;/a&gt;，以前不能通过父表发布，只能通过子表发布，该库版本是PG11。&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Allow partitioned tables to be logically replicated via &lt;a href="https://www.postgresql.org/docs/13/sql-createpublication.html" target="_blank" rel="noreferrer"&gt;publications&lt;/a&gt; (Amit Langote) &lt;a href="https://postgr.es/c/17b9e7f9f" target="_blank" rel="noreferrer"&gt;§&lt;/a&gt; &lt;a href="https://postgr.es/c/83fd4532a" target="_blank" rel="noreferrer"&gt;§&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Previously, partitions had to be replicated individually. Now a partitioned table can be published explicitly, causing all its partitions to be published automatically. Addition/removal of a partition causes it to be likewise added to or removed from the publication. The &lt;a href="https://www.postgresql.org/docs/13/sql-createpublication.html" target="_blank" rel="noreferrer"&gt;&lt;code&gt;CREATE PUBLICATION&lt;/code&gt;&lt;/a&gt; option &lt;code&gt;publish_via_partition_root&lt;/code&gt; controls whether changes to partitions are published as their own changes or their parent&amp;rsquo;s.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;初步知道问题后，因为情况紧急，可以通过3个办法来临时解决：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;26年新分区添加主键&lt;/li&gt;
&lt;li&gt;26年新分区设置replica identity full&lt;/li&gt;
&lt;li&gt;26年新分区取消发布表&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因为恢复时间都差不多，所以从减少运维成本的角度，通过添加主键恢复，至少先让业务不报错。&lt;/p&gt;

&lt;h2 class="relative group"&gt;根因分析
 &lt;div id="根因分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;问题看似清晰，就是“没有复制标识+发布过+没有主键”导致不能更新，但是还有一些问题需要解答。&lt;/p&gt;

&lt;h3 class="relative group"&gt;疑问一：为什么update没有更新202601的数据（新分区根本没有数据），仍然报错
 &lt;div id="疑问一为什么update没有更新202601的数据新分区根本没有数据仍然报错" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%96%91%e9%97%ae%e4%b8%80%e4%b8%ba%e4%bb%80%e4%b9%88update%e6%b2%a1%e6%9c%89%e6%9b%b4%e6%96%b0202601%e7%9a%84%e6%95%b0%e6%8d%ae%e6%96%b0%e5%88%86%e5%8c%ba%e6%a0%b9%e6%9c%ac%e6%b2%a1%e6%9c%89%e6%95%b0%e6%8d%ae%e4%bb%8d%e7%84%b6%e6%8a%a5%e9%94%99" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;拿到SQL文本如下：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;UPDATE&lt;/span&gt; tablzl_202601
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;SET&lt;/span&gt; idid &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; date_updated &lt;span style="color:#f92672"&gt;=&lt;/span&gt; now()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;WHERE&lt;/span&gt; mykey &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;tablzl_202601&lt;/code&gt;表的分区键是&lt;code&gt;created_date&lt;/code&gt;，SQL条件就没有分区键，所以去更新202601分区发现连个主键都没有所以就报错了。&lt;/p&gt;
&lt;p&gt;至于检查是否有行和检查复制标识谁先，从&lt;code&gt;ExecSimpleRelationUpdate&lt;/code&gt;可以看到逻辑，这个函数在不同的PG版本中变化极小：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Find the searchslot tuple and update it with data in the slot,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * update the indexes, and execute any constraints and per-row triggers.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Caller is responsible for opening the indexes.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;ExecSimpleRelationUpdate&lt;/span&gt;(EState &lt;span style="color:#f92672"&gt;*&lt;/span&gt;estate, EPQState &lt;span style="color:#f92672"&gt;*&lt;/span&gt;epqstate,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						 TupleTableSlot &lt;span style="color:#f92672"&gt;*&lt;/span&gt;searchslot, TupleTableSlot &lt;span style="color:#f92672"&gt;*&lt;/span&gt;slot)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;CheckCmdReplicaIdentity&lt;/span&gt;(rel, CMD_UPDATE); &lt;span style="color:#75715e"&gt;//检查复制标识
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/* BEFORE ROW UPDATE Triggers */&lt;/span&gt; &lt;span style="color:#75715e"&gt;//before ROW UPDATE trigger
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (resultRelInfo&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;ri_TrigDesc &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		resultRelInfo&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;ri_TrigDesc&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;trig_update_before_row)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		slot &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ExecBRUpdateTriggers&lt;/span&gt;(estate, epqstate, resultRelInfo,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;									&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;searchslot&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;tts_tuple&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;t_self,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;									NULL, slot);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (slot &lt;span style="color:#f92672"&gt;==&lt;/span&gt; NULL)		&lt;span style="color:#75715e"&gt;/* &amp;#34;do nothing&amp;#34; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			skip_tuple &lt;span style="color:#f92672"&gt;=&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;skip_tuple)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		List	 &lt;span style="color:#f92672"&gt;*&lt;/span&gt;recheckIndexes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; NIL;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* Check the constraints of the tuple */&lt;/span&gt; &lt;span style="color:#75715e"&gt;//检查约束
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (rel&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;rd_att&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;constr)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;ExecConstraints&lt;/span&gt;(resultRelInfo, slot, estate);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (resultRelInfo&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;ri_PartitionCheck)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;ExecPartitionCheck&lt;/span&gt;(resultRelInfo, slot, estate, true);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* Materialize slot into a tuple that we can scribble upon. */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		tuple &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ExecMaterializeSlot&lt;/span&gt;(slot);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* OK, update the tuple and index entries for it */&lt;/span&gt; &lt;span style="color:#75715e"&gt;//更新行
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;simple_heap_update&lt;/span&gt;(rel, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;searchslot&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;tts_tuple&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;t_self,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						 slot&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;tts_tuple);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (resultRelInfo&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;ri_NumIndices &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#75715e"&gt;//插入索引条目
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;HeapTupleIsHeapOnly&lt;/span&gt;(slot&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;tts_tuple))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			recheckIndexes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ExecInsertIndexTuples&lt;/span&gt;(slot, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;(tuple&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;t_self),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;												 estate, false, NULL,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;												 NIL);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* AFTER ROW UPDATE Triggers */&lt;/span&gt; &lt;span style="color:#75715e"&gt;//after ROW UPDATE trigger
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;ExecARUpdateTriggers&lt;/span&gt;(estate, resultRelInfo,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;							 &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;searchslot&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;tts_tuple&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;t_self,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;							 NULL, tuple, recheckIndexes, NULL);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;list_free&lt;/span&gt;(recheckIndexes);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;ExecSimpleRelationUpdate&lt;/code&gt;大致过程：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;检查复制标识&lt;/li&gt;
&lt;li&gt;before ROW UPDATE trigger&lt;/li&gt;
&lt;li&gt;检查约束（包括非分区约束和分区约束）&lt;/li&gt;
&lt;li&gt;更新行&lt;/li&gt;
&lt;li&gt;插入索引条目&lt;/li&gt;
&lt;li&gt;after ROW UPDATE trigger&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;所以pg逻辑就是先检查复制标识，然后才是更新行等等操作。&lt;/p&gt;
&lt;p&gt;虽然SQL条件没有分区键，但是加上分区键就会裁剪吗？答案是可能不会。&lt;/p&gt;
&lt;p&gt;分区裁剪的版本提升：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pg10刚支持声明式分区，没有enable_partition_pruning参数，可以通过constraint_exclusion在planning阶段裁剪。所以pg10没有query process pruning&lt;/li&gt;
&lt;li&gt;pg11支持query process pruning，&lt;a href="https://www.postgresql.org/docs/release/11.0/" target="_blank" rel="noreferrer"&gt;Allow partition elimination during query execution (David Rowley, Beena Emerson)&lt;/a&gt;。但只支持绑定变量裁剪，不支持非immutable函数裁剪（包括&lt;code&gt;now()&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.postgresql.org/docs/release/14.0/" target="_blank" rel="noreferrer"&gt;pg14&lt;/a&gt;支持最终裁剪，&lt;a href="https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=c5b7ba4e6" target="_blank" rel="noreferrer"&gt;This wins in UPDATEs on partitioned tables when only some of the partitions will actually receive updates&lt;/a&gt;。即支持非immutable函数裁剪&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因为pg11不支持now()裁剪，如果业务SQL加now()条件不会触发裁剪，仍然会报错。但是如果业务通过绑定变量传入，是会触发裁剪的，也就不会报错。注意，这个报错指的是更新202512的数据不会在202601分区上报错，更新202601的数据该报错还是报错。&lt;/p&gt;

&lt;h3 class="relative group"&gt;疑问二：表是20251226创建的,为什么是10月30日发现有问题
 &lt;div id="疑问二表是20251226创建的为什么是10月30日发现有问题" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%96%91%e9%97%ae%e4%ba%8c%e8%a1%a8%e6%98%af20251226%e5%88%9b%e5%bb%ba%e7%9a%84%e4%b8%ba%e4%bb%80%e4%b9%88%e6%98%af10%e6%9c%8830%e6%97%a5%e5%8f%91%e7%8e%b0%e6%9c%89%e9%97%ae%e9%a2%98" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;这个就更简单了，“没有复制标识+发布过+没有主键”是且的关系。&lt;/p&gt;
&lt;p&gt;虽然新分区建的比较早，但发布表的时间是12月29日晚20:47&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cat postgresql&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;29&lt;/span&gt;.csv.bak &lt;span style="color:#f92672"&gt;|&lt;/span&gt;grep &lt;span style="color:#e6db74"&gt;&amp;#34;alter publication&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2025&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;48&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;07&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;730&lt;/span&gt; CST,&lt;span style="color:#e6db74"&gt;&amp;#34;userlzlreplication&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,xxx&lt;span style="color:#e6db74"&gt;&amp;#34;statement: alter publication publzl add table &amp;#34;&amp;#34;public&amp;#34;&amp;#34;.&amp;#34;&amp;#34;tablzl_202601&amp;#34;&amp;#34;, &amp;#34;&amp;#34;public&amp;#34;&amp;#34;.&amp;#34;&amp;#34;tablzl_202602&amp;#34;&amp;#34;,...,,,,,,,,,&amp;#34;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;首次报错时间是12月29日晚22:26，也就是1个半小时左右以后：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cat postgresql&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;29&lt;/span&gt;.csv.bak &lt;span style="color:#f92672"&gt;|&lt;/span&gt;grep &lt;span style="color:#e6db74"&gt;&amp;#34;REPLICA IDENTITY&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2025&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;26&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;404&lt;/span&gt; CST,&lt;span style="color:#e6db74"&gt;&amp;#34;userlzlreplication&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;375121&lt;/span&gt;,xxx,&lt;span style="color:#e6db74"&gt;&amp;#34;cannot update table &amp;#34;&amp;#34;tablzl_202601&amp;#34;&amp;#34; because it does not have a replica identity and publishes updates&amp;#34;&lt;/span&gt;,,&lt;span style="color:#e6db74"&gt;&amp;#34;To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.&amp;#34;&lt;/span&gt;,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;UPDATE tablzl&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 class="relative group"&gt;总结
 &lt;div id="总结" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%80%bb%e7%bb%93" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;原因概述：如果父表没有主键，新分区partition of创建时当然也不会有主键，老的子分区通过子分区主键实现，新的子分区没有去主动创建主键，导致202601主键缺失。链路同步需要依赖主键（default）作复制标识，没有复制标识会导致无法同步给下游，也会导致发布以后update/delete语句无法正常执行。在PG 11中，update SQL本身即使包含分区键条件，也&lt;em&gt;可能&lt;/em&gt;会去访问新分区。&lt;/p&gt;
&lt;p&gt;运气成分：因为各种原因，这个库提前发现了这个问题。在31号我们有1天的buffer来补救所有数据库实例，至少保证1号新分区数据update别报错，不然大概率2026年1月1日多个系统将原地爆炸。&lt;/p&gt;
&lt;p&gt;临时措施（三选一）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;26年新分区添加主键&lt;/li&gt;
&lt;li&gt;26年新分区设置replica identity full&lt;/li&gt;
&lt;li&gt;26年新分区取消发布表&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对于复制链路的优化：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;应该提前发现没有主键的表，不然直接发布的话，可能会导致业务侧更新失败&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对于分区管理的策略：&lt;/p&gt;
&lt;p&gt;PG的分区表非常灵活，而且一般开发弄不懂怎么去正确创建分区，再加上分区表在大概PG10-15之间有较多的重要新特性，加上PG分区表没有interval分区功能，分区表可能弄的乱七八糟，所以规范管理分区表显得尤为重要。分区表的特性和运维技巧见：&lt;a href="https://blog.csdn.net/qq_40687433/article/details/132525655?spm=1001.2014.3001.5501" target="_blank" rel="noreferrer"&gt;PostgreSQL分区表&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;针对管理手段就不说了，&lt;/p&gt;
&lt;p&gt;针对管理目标：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;以主表结构为标准结构，即主表面向开发，它上面应该有主键、索引、复制标识（pg版本不支持除外）&lt;/li&gt;
&lt;li&gt;主表与子表保持一致，使用partition of创建新分区（是的，我不推荐attach）&lt;/li&gt;
&lt;li&gt;子表与子表保持一致&lt;/li&gt;
&lt;li&gt;提前创建新分区，分区数据量不宜过多&lt;/li&gt;
&lt;li&gt;default分区不建议创建，如果创建必须监控其写入情况&lt;/li&gt;
&lt;li&gt;频繁访问的表的SQL必须包含分区键，使用分区裁剪，不然改造为普通表&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;ref
 &lt;div id="ref" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#ref" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.postgresql.org/docs/release/10.0/" target="_blank" rel="noreferrer"&gt;https://www.postgresql.org/docs/release/10.0/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.postgresql.org/docs/release/11.0/" target="_blank" rel="noreferrer"&gt;https://www.postgresql.org/docs/release/11.0/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.postgresql.org/docs/release/12.0/" target="_blank" rel="noreferrer"&gt;https://www.postgresql.org/docs/release/12.0/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.postgresql.org/docs/release/13.0/" target="_blank" rel="noreferrer"&gt;https://www.postgresql.org/docs/release/13.0/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.postgresql.org/docs/release/14.0/" target="_blank" rel="noreferrer"&gt;https://www.postgresql.org/docs/release/14.0/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;src/backend/executor/execReplication.c&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.csdn.net/qq_40687433/article/details/132525655?spm=1001.2014.3001.5501" target="_blank" rel="noreferrer"&gt;PostgreSQL分区表&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>案例-行锁与LWlock-lockmanger</title><link>https://lastdba.com/2025/12/21/%E6%A1%88%E4%BE%8B-%E8%A1%8C%E9%94%81%E4%B8%8Elwlock-lockmanger/</link><pubDate>Sun, 21 Dec 2025 00:00:00 +0000</pubDate><guid>https://lastdba.com/2025/12/21/%E6%A1%88%E4%BE%8B-%E8%A1%8C%E9%94%81%E4%B8%8Elwlock-lockmanger/</guid><description>&lt;h2 class="relative group"&gt;现象
 &lt;div id="现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;数据库有大量行锁和少部分LWlock lockmanger，cpu打满，活动会话飙升。锁对应的block pid在变化，未见明显长事务阻塞。
(脑补cpu和活动会话高）&lt;/p&gt;</description><content:encoded>
&lt;h2 class="relative group"&gt;现象
 &lt;div id="现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;数据库有大量行锁和少部分LWlock lockmanger，cpu打满，活动会话飙升。锁对应的block pid在变化，未见明显长事务阻塞。
(脑补cpu和活动会话高）&lt;/p&gt;
&lt;p&gt;大量的锁对于的sql如下：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;UPDATE&lt;/span&gt; lzl_record &lt;span style="color:#66d9ef"&gt;SET&lt;/span&gt; rc_lzl1&lt;span style="color:#f92672"&gt;=&lt;/span&gt; rc_lzl1 &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, pc_lzl2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; pc_lzl2 &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, rc_lzl3 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; rc_lzl3 &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; lzl_id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 class="relative group"&gt;分析
 &lt;div id="分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;SQL未见并发上涨
 &lt;div id="sql未见并发上涨" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#sql%e6%9c%aa%e8%a7%81%e5%b9%b6%e5%8f%91%e4%b8%8a%e6%b6%a8" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;从hit和cpu的关联性看，可以从sql的hit分析。其中那个UPDATE sql占比80%左右，该sql的执行次数没有变化，但blks hit明显异常。&lt;/p&gt;
&lt;p&gt;同时分析元数据访问，快照内均元数据表没有访问特别高的。&lt;/p&gt;
&lt;p&gt;从现象分析看不出来SQL并发上涨，也看不出来元数据异常。SQL hit上涨暂时看不出来为什么。&lt;/p&gt;

&lt;h3 class="relative group"&gt;LWlock lockmanager分析
 &lt;div id="lwlock-lockmanager分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#lwlock-lockmanager%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;因为SQL本身简单，lzl_record表的lzl_id字段是唯一字段，也就是通过唯一键进行更新。&lt;/p&gt;
&lt;p&gt;现场的等待事件除了大量的显示锁以外，还有LWlock lockmanager。&lt;/p&gt;
&lt;p&gt;但表是普通表不是分区表，且表上只有4、5个索引。&lt;/p&gt;
&lt;p&gt;LWlock lockmanger跟没有用到fast path有关系，而简单的查询、DML可以用到fastpath&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Weak relation locks. SELECT, INSERT, UPDATE, and DELETE must acquire a
lock on every relation they operate on, as well as various system catalogs
that can be used internally. Many DML operations can proceed in parallel
against the same table at the same time; only DDL operations such as
CLUSTER, ALTER TABLE, or DROP &amp;ndash; or explicit user action such as LOCK TABLE
&amp;ndash; will create lock conflicts with the &amp;ldquo;weak&amp;rdquo; locks (AccessShareLock,
RowShareLock, RowExclusiveLock) acquired by DML operations.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;所以，一个不超过访问16个relation（含索引）的SELECT/DML是可以用到fastpath的，就不应该有很多LWlock lockmanager。&lt;/p&gt;
&lt;p&gt;但是，DML肯定不能简单的用fastpath，fastpath是完全本地化处理锁，DML肯定需要校验其他会话是否持有行，需要访问共享内存。再加上SQL通过唯一字段更新还能有行锁，说明肯定更新的是同一行。&lt;/p&gt;
&lt;p&gt;从日志上可以看到更新同一行的情况，其中一行有锁等待的更新有上万次。&lt;/p&gt;

&lt;h2 class="relative group"&gt;压测
 &lt;div id="压测" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%8e%8b%e6%b5%8b" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;压测同一行更新产生LWLock LockManager
 &lt;div id="压测同一行更新产生lwlock-lockmanager" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%8e%8b%e6%b5%8b%e5%90%8c%e4%b8%80%e8%a1%8c%e6%9b%b4%e6%96%b0%e4%ba%a7%e7%94%9flwlock-lockmanager" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;出于行锁肯定不能仅fastpath的考虑，以及LWLock LockManager会降低数据库性能的经验，压测不同场景性能情况。&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;#prompt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;给我一个pgbench压测脚本
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;表结构：主键,唯一字段+唯一索引，其他字段
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;更新：通过唯一字段更新
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;压测重复更新同一行数据，也就是重复行锁更新
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;压测随机更新某一行数据，也就是无行锁更新&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;脚本略，套餐20c96g&lt;/p&gt;
&lt;p&gt;pgbench命令如下&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pgbench -h localhost -p $PGPORT -d lzldb -U dbmgr -f update_same_unique_key.sql -c &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt; -j &lt;span style="color:#ae81ff"&gt;32&lt;/span&gt; -T &lt;span style="color:#ae81ff"&gt;600&lt;/span&gt; -r -S
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pgbench -h localhost -p $PGPORT -d lzldb -U dbmgr -f update_random_unique_key.sql -c &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt; -j &lt;span style="color:#ae81ff"&gt;32&lt;/span&gt; -T &lt;span style="color:#ae81ff"&gt;600&lt;/span&gt; -r -S&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;压测时的等待事件：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;--更新同一行，常见2次等待
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; usename &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; wait_event &lt;span style="color:#f92672"&gt;|&lt;/span&gt; wait_event_type &lt;span style="color:#f92672"&gt;|&lt;/span&gt; cnt 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;----------+--------+---------------------+-----------------+-----
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; LockManager &lt;span style="color:#f92672"&gt;|&lt;/span&gt; LWLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;105&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; transactionid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Lock&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;61&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; tuple &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Lock&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;25&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; WALSync &lt;span style="color:#f92672"&gt;|&lt;/span&gt; IO &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; usename &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; wait_event &lt;span style="color:#f92672"&gt;|&lt;/span&gt; wait_event_type &lt;span style="color:#f92672"&gt;|&lt;/span&gt; cnt 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;----------+--------+---------------------+-----------------+-----
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; transactionid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Lock&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;180&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; LockManager &lt;span style="color:#f92672"&gt;|&lt;/span&gt; LWLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; tuple &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Lock&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; WALSync &lt;span style="color:#f92672"&gt;|&lt;/span&gt; IO &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--更新不同行，常见2次等待
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;usename &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; wait_event &lt;span style="color:#f92672"&gt;|&lt;/span&gt; wait_event_type &lt;span style="color:#f92672"&gt;|&lt;/span&gt; cnt 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;----------+---------------------+---------------------+-----------------+-----
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;106&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; idle &lt;span style="color:#f92672"&gt;|&lt;/span&gt; ClientRead &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Client &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;34&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; idle &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;transaction&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; ClientRead &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Client &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;25&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; WALWrite &lt;span style="color:#f92672"&gt;|&lt;/span&gt; LWLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; BufferMapping &lt;span style="color:#f92672"&gt;|&lt;/span&gt; LWLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; idle &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;transaction&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; idle &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;transaction&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; WALWrite &lt;span style="color:#f92672"&gt;|&lt;/span&gt; LWLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; usename &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; wait_event &lt;span style="color:#f92672"&gt;|&lt;/span&gt; wait_event_type &lt;span style="color:#f92672"&gt;|&lt;/span&gt; cnt 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;----------+---------------------+---------------------+-----------------+-----
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;117&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; idle &lt;span style="color:#f92672"&gt;|&lt;/span&gt; ClientRead &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Client &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; idle &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;transaction&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; ClientRead &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Client &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; WALWrite &lt;span style="color:#f92672"&gt;|&lt;/span&gt; LWLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; XactGroupUpdate &lt;span style="color:#f92672"&gt;|&lt;/span&gt; IPC &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; WALSync &lt;span style="color:#f92672"&gt;|&lt;/span&gt; IO &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; XactSLRU &lt;span style="color:#f92672"&gt;|&lt;/span&gt; LWLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; BufferContent &lt;span style="color:#f92672"&gt;|&lt;/span&gt; LWLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbmgr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; ClientRead &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Client &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;从等待事件上可以看出差异，更新同一行会出现LWLock LockManager甚至占比较高的情况，不同行基本都是等cpu。场景1与生产情况类似。&lt;/p&gt;

&lt;h2 class="relative group"&gt;行锁与fastpath浅析
 &lt;div id="行锁与fastpath浅析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%a1%8c%e9%94%81%e4%b8%8efastpath%e6%b5%85%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;lmgr readme对fastpath的解释：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Fast Path Locking
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-----------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Fast path locking is a special purpose mechanism designed to reduce the
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;overhead of taking and releasing certain types of locks which are taken
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;and released very frequently but rarely conflict. Currently, this includes
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;two categories of locks:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(1) Weak relation locks. SELECT, INSERT, UPDATE, and DELETE must acquire a
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lock on every relation they operate on, as well as various system catalogs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;that can be used internally. Many DML operations can proceed in parallel
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;against the same table at the same time; only DDL operations such as
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CLUSTER, ALTER TABLE, or DROP -- or explicit user action such as LOCK TABLE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-- will create lock conflicts with the &amp;#34;weak&amp;#34; locks (AccessShareLock,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;RowShareLock, RowExclusiveLock) acquired by DML operations.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;能使用fastpath的锁的条件&lt;code&gt;lmgr/lock.c&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * The fast-path lock mechanism is concerned only with relation locks on
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * unshared relations by backends bound to a database. The fast-path
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * mechanism exists mostly to accelerate acquisition and release of locks
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * that rarely conflict. Because ShareUpdateExclusiveLock is
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * self-conflicting, it can&amp;#39;t use the fast-path mechanism; but it also does
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * not conflict with any of the locks that do, so we can ignore it completely.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define EligibleForRelationFastPath(locktag, mode) \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	((locktag)-&amp;gt;locktag_lockmethodid == DEFAULT_LOCKMETHOD &amp;amp;&amp;amp; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	(locktag)-&amp;gt;locktag_type == LOCKTAG_RELATION &amp;amp;&amp;amp; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	(locktag)-&amp;gt;locktag_field1 == MyDatabaseId &amp;amp;&amp;amp; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	MyDatabaseId != InvalidOid &amp;amp;&amp;amp; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	(mode) &amp;lt; ShareUpdateExclusiveLock)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;SELECT/DML是可以使用fastpath的，但是仅限于locktype=relation。&lt;/p&gt;
&lt;p&gt;实际查看行锁时的锁情况：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--窗口1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;begin&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;update&lt;/span&gt; lzl1 &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; b&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;zzz&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--窗口2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;begin&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;update&lt;/span&gt; lzl1 &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; b&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;zzz&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--waiting
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--窗口3
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_locks &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; pid&lt;span style="color:#f92672"&gt;&amp;lt;&amp;gt;&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; pg_backend_pid()) &lt;span style="color:#66d9ef"&gt;order&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;by&lt;/span&gt; pid,locktype;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; locktype &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;database&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; relation &lt;span style="color:#f92672"&gt;|&lt;/span&gt; page &lt;span style="color:#f92672"&gt;|&lt;/span&gt; tuple &lt;span style="color:#f92672"&gt;|&lt;/span&gt; virtualxid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; transactionid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; classid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; objid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; objsubid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; virtualtransaction &lt;span style="color:#f92672"&gt;|&lt;/span&gt; pid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;mode&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;granted&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; fastpath 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;---------------+----------+----------+--------+--------+------------+---------------+---------+--------+----------+--------------------+--------+------------------+---------+----------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; relation &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4267681&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5290151&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4791&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;220559&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; RowExclusiveLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; transactionid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;170706189&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4791&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;220559&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; ExclusiveLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t &lt;span style="color:#f92672"&gt;|&lt;/span&gt; f
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; transactionid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;170706190&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4791&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;220559&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; ExclusiveLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t &lt;span style="color:#f92672"&gt;|&lt;/span&gt; f
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; transactionid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;170706187&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4791&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;220559&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; ShareLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; f &lt;span style="color:#f92672"&gt;|&lt;/span&gt; f
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tuple &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4267681&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5290151&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4791&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;220559&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; ExclusiveLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t &lt;span style="color:#f92672"&gt;|&lt;/span&gt; f
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; virtualxid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4791&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4791&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;220559&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; ExclusiveLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; relation &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4267681&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5290151&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;562&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;253641&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; RowExclusiveLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; transactionid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;170706187&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;562&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;253641&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; ExclusiveLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t &lt;span style="color:#f92672"&gt;|&lt;/span&gt; f
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; virtualxid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;562&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;562&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;253641&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; ExclusiveLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;pg的行锁实现比较复杂，不仅有tuple锁，还需要transactionid和relation锁。其中只有locktype=relation、virtualxid能用到fastpath，其他都用不到。&lt;/p&gt;
&lt;p&gt;对比没有行锁：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--窗口1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;begin&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;update&lt;/span&gt; lzl1 &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; b&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;zzz&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--窗口2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;begin&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;update&lt;/span&gt; lzl1 &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; b&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;zzz&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--waiting
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_locks &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; pid&lt;span style="color:#f92672"&gt;&amp;lt;&amp;gt;&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; pg_backend_pid()) &lt;span style="color:#66d9ef"&gt;order&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;by&lt;/span&gt; pid,locktype;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; locktype &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;database&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; relation &lt;span style="color:#f92672"&gt;|&lt;/span&gt; page &lt;span style="color:#f92672"&gt;|&lt;/span&gt; tuple &lt;span style="color:#f92672"&gt;|&lt;/span&gt; virtualxid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; transactionid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; classid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; objid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; objsubid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; virtualtransaction &lt;span style="color:#f92672"&gt;|&lt;/span&gt; pid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;mode&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;granted&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; fastpath 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;---------------+----------+----------+--------+--------+------------+---------------+---------+--------+----------+--------------------+--------+------------------+---------+----------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; relation &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4267681&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5290151&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4792&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;220559&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; RowExclusiveLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; relation &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4267681&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5290151&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4792&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;220559&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; AccessShareLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; transactionid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;170706214&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4792&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;220559&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; ExclusiveLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t &lt;span style="color:#f92672"&gt;|&lt;/span&gt; f
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; virtualxid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4792&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4792&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;220559&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; ExclusiveLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; relation &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4267681&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5290151&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;563&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;253641&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; AccessShareLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; relation &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4267681&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5290151&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;563&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;253641&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; RowExclusiveLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; transactionid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;170706212&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;563&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;253641&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; ExclusiveLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t &lt;span style="color:#f92672"&gt;|&lt;/span&gt; f
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; virtualxid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;563&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;563&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;253641&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; ExclusiveLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;fastpath=f的也就少了2、3个。2个会话持有的transactionid锁是肯定用不到fastpath了。&lt;/p&gt;
&lt;p&gt;总结使用fastpath锁机制的场景（且）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;锁等级&amp;lt;=3，即SELECT/DML语句&lt;/li&gt;
&lt;li&gt;locktype=relation。pg的行锁还至少需要transactionid和tuple锁，所以这俩用不到fastpath&lt;/li&gt;
&lt;li&gt;relation数少于16个（一般分区表全分区访问就超了）&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;总结
 &lt;div id="总结" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%80%bb%e7%bb%93" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;1.行锁是因是果，是行锁的问题还是数据库性能下降SQL跑的慢了出现行锁？&lt;/p&gt;
&lt;p&gt;行锁是因。sql执行次数没有变化，但是sql的传参从离散变成集中，即更新同一行的情况明显增加。从压测数据来看更新同一行会出现行锁和LWLock LockManager的等待。&lt;/p&gt;
&lt;p&gt;2.sql执行次数没有上涨，SQL性能是否下降？&lt;/p&gt;
&lt;p&gt;SQL性能其实是下降了，但是索引肯定没有走错，只是因为反复更新了同一行。&lt;/p&gt;
&lt;p&gt;解决方案：&lt;/p&gt;
&lt;p&gt;从业务层了解SQL是某接口开关调用后讲调用次数更新到表里。如果是同一接口反复调用，是可能出现反复更新同一行的情况的。所以，减少同一接口反复调用或者更大批次的更新数据库，预计可以减缓这个问题。&lt;/p&gt;</content:encoded></item><item><title>案例-从distinct不准确到DISTINCT的计算原理</title><link>https://lastdba.com/2025/10/19/%E6%A1%88%E4%BE%8B-%E4%BB%8Edistinct%E4%B8%8D%E5%87%86%E7%A1%AE%E5%88%B0distinct%E7%9A%84%E8%AE%A1%E7%AE%97%E5%8E%9F%E7%90%86/</link><pubDate>Sun, 19 Oct 2025 00:00:00 +0000</pubDate><guid>https://lastdba.com/2025/10/19/%E6%A1%88%E4%BE%8B-%E4%BB%8Edistinct%E4%B8%8D%E5%87%86%E7%A1%AE%E5%88%B0distinct%E7%9A%84%E8%AE%A1%E7%AE%97%E5%8E%9F%E7%90%86/</guid><description>&lt;h2 class="relative group"&gt;问题现象
 &lt;div id="问题现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;统计信息的n_distinct不准确&lt;/p&gt;
&lt;p&gt;这个问题在多个库中出现，例如：&lt;/p&gt;
&lt;p&gt;表有2亿行数据，真实DISTINCT有800w，统计信息中的DISTINCT只有4w。&lt;/p&gt;</description><content:encoded>
&lt;h2 class="relative group"&gt;问题现象
 &lt;div id="问题现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;统计信息的n_distinct不准确&lt;/p&gt;
&lt;p&gt;这个问题在多个库中出现，例如：&lt;/p&gt;
&lt;p&gt;表有2亿行数据，真实DISTINCT有800w，统计信息中的DISTINCT只有4w。&lt;/p&gt;

&lt;h2 class="relative group"&gt;问题分析
 &lt;div id="问题分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;采样模型
 &lt;div id="采样模型" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%87%87%e6%a0%b7%e6%a8%a1%e5%9e%8b" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/7e0b33a60cf4.png" alt="备库是否有自己的统计信息？ · PostgreSQL学徒" /&gt;&lt;/p&gt;
&lt;p&gt;默认default_statistics_target=100，即采集30000 pages中的30000行数据。&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;verbose&lt;/span&gt; tablzl1;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;INFO: &lt;span style="color:#ae81ff"&gt;00000&lt;/span&gt;: analyzing &lt;span style="color:#e6db74"&gt;&amp;#34;public.tablzl1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;LOCATION&lt;/span&gt;: do_analyze_rel, &lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt;.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;332&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;INFO: &lt;span style="color:#ae81ff"&gt;00000&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;tablzl1&amp;#34;&lt;/span&gt;: scanned &lt;span style="color:#ae81ff"&gt;30000&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;22963751&lt;/span&gt; pages, containing &lt;span style="color:#ae81ff"&gt;1061942&lt;/span&gt; live &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;and&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3953&lt;/span&gt; dead &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;; &lt;span style="color:#ae81ff"&gt;30000&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; sample, &lt;span style="color:#ae81ff"&gt;812872389&lt;/span&gt; estimated total &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;LOCATION&lt;/span&gt;: acquire_sample_rows, &lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt;.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;1340&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;注意 &amp;ldquo;scanned 30000&amp;rdquo; 和 &amp;ldquo;30000 rows in sample&amp;rdquo;&lt;/p&gt;

&lt;h3 class="relative group"&gt;distinct预估算法
 &lt;div id="distinct预估算法" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#distinct%e9%a2%84%e4%bc%b0%e7%ae%97%e6%b3%95" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;distinct的预估算法&lt;code&gt;analyze.c&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/*----------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * Estimate the number of distinct values using the estimator
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * proposed by Haas and Stokes in IBM Research Report RJ 10025:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 *		n*d / (n - f1 + f1*n/N)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * where f1 is the number of distinct values that occurred
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * exactly once in our sample of n rows (from a total of N),
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * and d is the total number of distinct values in the sample.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * This is their Duj1 estimator; the other estimators they
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * recommend are considerably more complex, and are numerically
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * very unstable when n is much smaller than N.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * In this calculation, we consider only non-nulls. We used to
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * include rows with null values in the n and N counts, but that
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * leads to inaccurate answers in columns with many nulls, and
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * it&amp;#39;s intuitively bogus anyway considering the desired result is
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * the number of distinct non-null values.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * We assume (not very reliably!) that all the multiply-occurring
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * values are reflected in the final track[] list, and the other
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * nonnull values all appeared but once. (XXX this usually
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * results in a drastic overestimate of ndistinct. Can we do
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * any better?)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 *----------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;			f1 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; nonnull_cnt &lt;span style="color:#f92672"&gt;-&lt;/span&gt; summultiple;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;			d &lt;span style="color:#f92672"&gt;=&lt;/span&gt; f1 &lt;span style="color:#f92672"&gt;+&lt;/span&gt; nmultiple;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;double&lt;/span&gt;		n &lt;span style="color:#f92672"&gt;=&lt;/span&gt; samplerows &lt;span style="color:#f92672"&gt;-&lt;/span&gt; null_cnt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;double&lt;/span&gt;		N &lt;span style="color:#f92672"&gt;=&lt;/span&gt; totalrows &lt;span style="color:#f92672"&gt;*&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;1.0&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; stats&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;stanullfrac);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;double&lt;/span&gt;		stadistinct;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;n*d / (n - f1 + f1*n/N)&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;n&lt;/code&gt; = 样本行数（扫描的行数）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;d&lt;/code&gt; = 样本中发现的distinct值的数量&lt;/li&gt;
&lt;li&gt;&lt;code&gt;f1&lt;/code&gt; = 样本中只出现一次值的数量&lt;/li&gt;
&lt;li&gt;&lt;code&gt;N&lt;/code&gt; = 表的总行数&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;算法论文：&lt;a href="https://hugepdf.com/download/download-extended-version-of-this-paper_pdf" target="_blank" rel="noreferrer"&gt;https://hugepdf.com/download/download-extended-version-of-this-paper_pdf&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;论文看起来比较费劲，下面做一些假设来理解这个disticnt算法：&lt;/p&gt;
&lt;p&gt;1.假设全是出现一次值，且表很大n&amp;laquo;N，即f1=d，n/N=0&lt;/p&gt;
&lt;p&gt;&lt;code&gt;d*d / (d - d + d*0)=d*2/0&lt;/code&gt;， 这应该是-1了.&lt;/p&gt;
&lt;p&gt;2.假设全是出现一次值，且表很小n=N，即f1=d，n/N=1&lt;/p&gt;
&lt;p&gt;&lt;code&gt;n*d / (n - d + d*1)=d&lt;/code&gt;，即采集的distinct数，也等于采集的行数&lt;/p&gt;
&lt;p&gt;3.假设采集样本中没有只出现一次值，即f1=0，&lt;/p&gt;
&lt;p&gt;&lt;code&gt;n*d / (n - f1 + f1*n/N)=n*d / (n)=n*d / (n)=d&lt;/code&gt; ，也就是采样中的distinct数.&lt;/p&gt;
&lt;p&gt;如果一个列均是插入几条同样的值，然后再插入几条同样的值，比如：&lt;/p&gt;
&lt;p&gt;11,2,2,2,2,3,3,3,..&lt;/p&gt;
&lt;p&gt;3.1且表小，3w行采集全部采完，真实distinct=10000（假设），预估distinct=d=10000&lt;/p&gt;
&lt;p&gt;3.2且表大，采样中有重复出现的值，也有出现一次值（因为某个重复数据只采到一条），即n=30000,n/N=0，&lt;/p&gt;
&lt;p&gt;&lt;code&gt;n*d / (n - f1 + f1*n/N)=n*d / (n - f1)=30000*d/(30000-f1)&lt;/code&gt;，也就是采样中的distinct数越大，预估的distinct越大；采样只出现一次值数越大，预估的distinct越大&lt;/p&gt;
&lt;p&gt;总结：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;distinct预估跟采样中的distinct数、只出现一次值数直接相关&lt;/li&gt;
&lt;li&gt;如果只出现一次值数=0，那么采样越多，预估的distinct越大&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;验证
 &lt;div id="验证" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%aa%8c%e8%af%81" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;由于默认采样数最大是3w行，也就是说这种采样算法只要超过3w，即表比较大的时候，预估distinct很可能偏小。注意这里的数据不能有太多唯一值。&lt;/p&gt;
&lt;p&gt;测试一张表不同采样数的差异：&lt;/p&gt;
&lt;p&gt;表有reltuples=8亿，relpages=2kw，size=175GB，真实的某字段distinct 1亿&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;target statistics&lt;/th&gt;
 &lt;th&gt;pages采样比例（1）&lt;/th&gt;
 &lt;th&gt;tuples采样比例（1）&lt;/th&gt;
 &lt;th&gt;n_distinct&lt;/th&gt;
 &lt;th&gt;执行时间&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;50&lt;/td&gt;
 &lt;td&gt;0.00075&lt;/td&gt;
 &lt;td&gt;0.00001875&lt;/td&gt;
 &lt;td&gt;6w&lt;/td&gt;
 &lt;td&gt;2秒&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;100&lt;/td&gt;
 &lt;td&gt;0.0015&lt;/td&gt;
 &lt;td&gt;0.0000375&lt;/td&gt;
 &lt;td&gt;11w&lt;/td&gt;
 &lt;td&gt;5秒&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;1000&lt;/td&gt;
 &lt;td&gt;0.015&lt;/td&gt;
 &lt;td&gt;0.000375&lt;/td&gt;
 &lt;td&gt;103w&lt;/td&gt;
 &lt;td&gt;58秒&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;3000&lt;/td&gt;
 &lt;td&gt;0.045&lt;/td&gt;
 &lt;td&gt;0.001125&lt;/td&gt;
 &lt;td&gt;268w&lt;/td&gt;
 &lt;td&gt;3分01秒&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;10000&lt;/td&gt;
 &lt;td&gt;0.15&lt;/td&gt;
 &lt;td&gt;0.00375&lt;/td&gt;
 &lt;td&gt;675w&lt;/td&gt;
 &lt;td&gt;7分21秒&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;（target statistics 最大值10000）&lt;/p&gt;
&lt;p&gt;可以粗糙的总结：n_distinct和analyze的执行时间随采样数量成倍增长。&lt;/p&gt;
&lt;p&gt;n_distinct随采样数量增长，pages和tuples却一直都很准确。&lt;/p&gt;

&lt;h3 class="relative group"&gt;解决
 &lt;div id="解决" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%a7%a3%e5%86%b3" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;由于表特别大，可以考虑改造分区表或根据实际SQL进行优化&lt;/p&gt;
&lt;p&gt;还可以调整收集阈值，默认阈值&lt;code&gt;default_statistics_target=100&lt;/code&gt;，即3w个pages中的3w条数据。&lt;/p&gt;
&lt;p&gt;临时方案：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; default_statistics_target&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3000&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt; tab1;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;长期方案：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;alter&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; tab1 &lt;span style="color:#66d9ef"&gt;alter&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;column&lt;/span&gt; col1 &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;STATISTICS&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3000&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;注意：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;列的收集阈值优先级最高，大于&lt;code&gt;default_statistics_target&lt;/code&gt;参数&lt;/li&gt;
&lt;li&gt;收集阈值最大为10000&lt;/li&gt;
&lt;li&gt;表的收集阈值为最大的列阈值：&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * Determine how many rows we need to sample, using the worst case from
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * all analyzable columns. We use a lower bound of 100 rows to avoid
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * possible overflow in Vitter&amp;#39;s algorithm. (Note: that will also be the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * target in the corner case where there are no analyzable columns.)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	targrows &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (i &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; i &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; attr_cnt; i&lt;span style="color:#f92672"&gt;++&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (targrows &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; vacattrstats[i]&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;minrows)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			targrows &lt;span style="color:#f92672"&gt;=&lt;/span&gt; vacattrstats[i]&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;minrows;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (ind &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; ind &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; nindexes; ind&lt;span style="color:#f92672"&gt;++&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		AnlIndexData &lt;span style="color:#f92672"&gt;*&lt;/span&gt;thisdata &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;indexdata[ind];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (i &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; i &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; thisdata&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;attr_cnt; i&lt;span style="color:#f92672"&gt;++&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (targrows &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; thisdata&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;vacattrstats[i]&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;minrows)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				targrows &lt;span style="color:#f92672"&gt;=&lt;/span&gt; thisdata&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;vacattrstats[i]&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;minrows;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;如果执行&lt;code&gt;analyze&lt;/code&gt;发现收集多了或者少了，可以看下&lt;code&gt;pg_statistic&lt;/code&gt;是不是有设置字段&lt;code&gt;stattarget&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; attrelid::regclass,attname,attstattarget &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_attribute &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; attrelid &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;tab1&amp;#39;&lt;/span&gt;::regclass &lt;span style="color:#66d9ef"&gt;and&lt;/span&gt; attstattarget &lt;span style="color:#66d9ef"&gt;not&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; (&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 class="relative group"&gt;总结
 &lt;div id="总结" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%80%bb%e7%bb%93" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;对于大表，字段非唯一但distinct值比较高（符合真实场景），采样算法会低估distinct值，且跟采样比例正相关。默认的采样比例对于大表来说偏小，可以调大，但是最大也大不到哪去。&lt;/p&gt;</content:encoded></item><item><title>案例-添加索引性能下降和generic plan</title><link>https://lastdba.com/2025/09/13/%E6%A1%88%E4%BE%8B-%E6%B7%BB%E5%8A%A0%E7%B4%A2%E5%BC%95%E6%80%A7%E8%83%BD%E4%B8%8B%E9%99%8D%E5%92%8Cgeneric-plan/</link><pubDate>Sat, 13 Sep 2025 00:00:00 +0000</pubDate><guid>https://lastdba.com/2025/09/13/%E6%A1%88%E4%BE%8B-%E6%B7%BB%E5%8A%A0%E7%B4%A2%E5%BC%95%E6%80%A7%E8%83%BD%E4%B8%8B%E9%99%8D%E5%92%8Cgeneric-plan/</guid><description>&lt;h2 class="relative group"&gt;问题现象
 &lt;div id="问题现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;前晚添加索引，第二天早上cpu打爆，sql容易定位，问题sql就1条。该sql跑了30多s，但是昨天跑3s左右，所以要看下前后执行计划变化。&lt;/p&gt;</description><content:encoded>
&lt;h2 class="relative group"&gt;问题现象
 &lt;div id="问题现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;前晚添加索引，第二天早上cpu打爆，sql容易定位，问题sql就1条。该sql跑了30多s，但是昨天跑3s左右，所以要看下前后执行计划变化。&lt;/p&gt;
&lt;p&gt;执行计划只贴关键部分。&lt;/p&gt;
&lt;p&gt;加索引前的执行计划：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Nested Loop (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;19&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;92&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;2259694&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;265822&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;33&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; uk_lzl_task &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_task t (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;29&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;20007&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;99&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;195&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((created_by)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;LIUZHILONG62&amp;#39;&lt;/span&gt;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Append (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;19&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;63&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;11337&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;14842&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;57&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Bitmap Heap Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_202501 cc_1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;19&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;63&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;3053&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;69&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1467&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;66&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Recheck&lt;/span&gt; Cond: ((task_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (t.task_no)::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((created_date &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2025-01-07 09:00:00&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (created_date &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2025-09-03 12:56:44.973&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Bitmap &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_202501_task_no_idx (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;19&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1594&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((task_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (t.task_no)::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Bitmap Heap Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_202502 cc_2 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;67&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;3066&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;85&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1604&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;66&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Recheck&lt;/span&gt; Cond: ((task_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (t.task_no)::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((created_date &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2025-01-07 09:00:00&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (created_date &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2025-09-03 12:56:44.973&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Bitmap &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_202502_task_no_idx (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1605&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((task_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (t.task_no)::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; lzl_202503_task_no_idx &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_202503 cc_3 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;1362&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;61&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1637&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;57&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((task_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (t.task_no)::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((created_date &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2025-01-07 09:00:00&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (created_date &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2025-09-03 12:56:44.973&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; lzl_202504_task_no_idx &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_202504 cc_4 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;604&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;64&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1795&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((task_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (t.task_no)::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((created_date &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2025-01-07 09:00:00&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (created_date &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2025-09-03 12:56:44.973&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; lzl_202505_task_no_idx &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_202505 cc_5 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;445&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1450&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((task_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (t.task_no)::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((created_date &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2025-01-07 09:00:00&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (created_date &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2025-09-03 12:56:44.973&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; lzl_202506_task_no_idx &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_202506 cc_6 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;583&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;94&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1675&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((task_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (t.task_no)::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((created_date &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2025-01-07 09:00:00&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (created_date &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2025-09-03 12:56:44.973&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; lzl_202507_task_no_idx &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_202507 cc_7 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;633&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;45&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1973&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((task_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (t.task_no)::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((created_date &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2025-01-07 09:00:00&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (created_date &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2025-09-03 12:56:44.973&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; lzl_202508_task_no_idx &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_202508 cc_8 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;619&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1720&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((task_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (t.task_no)::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((created_date &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2025-01-07 09:00:00&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (created_date &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2025-09-03 12:56:44.973&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; lzl_202509_task_no_idx &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_202509 cc_9 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;893&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;03&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1521&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((task_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (t.task_no)::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((created_date &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2025-01-07 09:00:00&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (created_date &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2025-09-03 12:56:44.973&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;created_date时间范围，找1年的数据，前晚变更加的索引是created_date。&lt;/p&gt;
&lt;p&gt;加索引后的执行计划：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Hash &lt;span style="color:#66d9ef"&gt;Join&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;63&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;37&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;23740&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;82&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;191&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;33&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Hash Cond: ((cc.task_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (t.task_no)::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Append (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;23376&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;98&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;114435&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;58&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Subplans Removed: &lt;span style="color:#ae81ff"&gt;28&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_lzltab_202501_created_date &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzltab_202501 cc_1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;1450&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;59&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8958&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;66&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((created_date &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (created_date &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_lzltab_202502_created_date &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzltab_202502 cc_2 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;1822&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;73&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;7405&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;66&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((created_date &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (created_date &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_lzltab_202503_created_date &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzltab_202503 cc_3 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;1430&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;03&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;7917&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;57&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((created_date &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (created_date &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_lzltab_202504_created_date &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzltab_202504 cc_4 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;2412&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;44&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;11041&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((created_date &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (created_date &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_lzltab_202505_created_date &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzltab_202505 cc_5 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;2260&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;73&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;13381&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((created_date &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (created_date &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_lzltab_202506_created_date &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzltab_202506 cc_6 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;3930&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;17832&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((created_date &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (created_date &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_lzltab_202507_created_date &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzltab_202507 cc_7 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;3878&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;77&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;21786&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((created_date &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (created_date &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_lzltab_202508_created_date &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzltab_202508 cc_8 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;4736&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;72&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;22033&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((created_date &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (created_date &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_lzltab_202509_created_date &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzltab_202509 cc_9 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;627&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;09&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1893&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((created_date &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (created_date &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Hash (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;63&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;03&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;63&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;03&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Bitmap Heap Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; ai_outbound_call_task t (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;99&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;63&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;03&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Recheck&lt;/span&gt; Cond: ((created_by)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;)::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Bitmap &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; idx_ai_call_task_c (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;99&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((created_by)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;)::text)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;新的执行计划从task_no索引变成走created_date索引，nl变成hash join。cost从2259694减少到23740，减少100倍。但是，实际执行时间增加了10倍左右。&lt;/p&gt;

&lt;h2 class="relative group"&gt;问题定位
 &lt;div id="问题定位" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e5%ae%9a%e4%bd%8d" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;从3个问题来带入分析定位：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;为什么优化人员建议了created_date索引？&lt;/li&gt;
&lt;li&gt;为什么走到了新的索引？&lt;/li&gt;
&lt;li&gt;为什么新的执行计划执行时间很长但预估rows很小？&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 class="relative group"&gt;为什么优化人员建议了created_date索引？
 &lt;div id="为什么优化人员建议了created_date索引" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e4%bc%98%e5%8c%96%e4%ba%ba%e5%91%98%e5%bb%ba%e8%ae%ae%e4%ba%86created_date%e7%b4%a2%e5%bc%95" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;如果直接把pg日志中参数回填到sql文本，执行计划其实是好的那一个，也就是跑3s的走task_no索引的plan。优化人员也这么跑了，发现还可以。但是生产环境却不是这个执行计划。&lt;/p&gt;
&lt;p&gt;即使强制不让走task_no索引，优化器选择全表扫描都不去走create date索引：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Hash Cond: (((cc.task_no)::text &lt;span style="color:#f92672"&gt;||&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (t.task_no)::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Append (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;2794425&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;58&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;22238757&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;57&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Seq Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzltab_202501 cc_1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;193060&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1585238&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;66&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((created_date &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2025-01-08 11:00:00&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (created_date &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2025-09-04 08:31:43&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Seq Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzltab_202502 cc_2 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;178567&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;54&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1480969&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;66&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((created_date &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2025-01-08 11:00:00&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (created_date &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2025-09-04 08:31:43&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Seq Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzltab_202503 cc_3 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;191073&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;34&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1583356&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;57&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这就很奇怪，自己怎么跑都走不到created_date烂索引，生产环境又是怎么走到created_date的？&lt;/p&gt;
&lt;p&gt;联想到有绑定变量，有可能会是generic plan。&lt;/p&gt;
&lt;p&gt;generic plan的特性：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;当&lt;code&gt;force_custom_plan =auto&lt;/code&gt;时，对比generic plan和avg(前五次硬解析的执行计划的代价)，如果generic plan更小就用generic plan，后续不再进行硬解析；否则每次都硬解析（见源码&lt;code&gt;choose_custom_plan&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;generic plan长什么样子跟绑定变量本身是多少没有关系&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;使用绑定变量传值很容易复现：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;PREPARE&lt;/span&gt; sql1(&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;,&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;,text) &lt;span style="color:#66d9ef"&gt;AS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;COUNT&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xxxxxxx...;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;EXECUTE&lt;/span&gt; sql1(&lt;span style="color:#e6db74"&gt;&amp;#39;2025-01-08 11:00:00&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;2025-09-04 08:31:43&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;LIUZHILONG62&amp;#39;&lt;/span&gt;); 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;12016&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;row&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Time: &lt;span style="color:#ae81ff"&gt;367&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;220&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;EXECUTE&lt;/span&gt; sql1(&lt;span style="color:#e6db74"&gt;&amp;#39;2025-01-08 11:00:00&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;2025-09-04 08:31:43&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;LIUZHILONG62&amp;#39;&lt;/span&gt;); 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;12016&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;row&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Time: &lt;span style="color:#ae81ff"&gt;254&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;386&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;EXECUTE&lt;/span&gt; sql1(&lt;span style="color:#e6db74"&gt;&amp;#39;2025-01-08 11:00:00&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;2025-09-04 08:31:43&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;LIUZHILONG62&amp;#39;&lt;/span&gt;); 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;12016&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;row&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Time: &lt;span style="color:#ae81ff"&gt;235&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;343&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;EXECUTE&lt;/span&gt; sql1(&lt;span style="color:#e6db74"&gt;&amp;#39;2025-01-08 11:00:00&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;2025-09-04 08:31:43&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;LIUZHILONG62&amp;#39;&lt;/span&gt;); 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;12016&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;row&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Time: &lt;span style="color:#ae81ff"&gt;234&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;110&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;EXECUTE&lt;/span&gt; sql1(&lt;span style="color:#e6db74"&gt;&amp;#39;2025-01-08 11:00:00&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;2025-09-04 08:31:43&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;LIUZHILONG62&amp;#39;&lt;/span&gt;); 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;12016&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;row&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Time: &lt;span style="color:#ae81ff"&gt;233&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;570&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;EXECUTE&lt;/span&gt; sql1(&lt;span style="color:#e6db74"&gt;&amp;#39;2025-01-08 11:00:00&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;2025-09-04 08:31:43&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;LIUZHILONG62&amp;#39;&lt;/span&gt;); 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;12016&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;row&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Time: &lt;span style="color:#ae81ff"&gt;70678&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;344&lt;/span&gt; ms (&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;678&lt;/span&gt;) &lt;span style="color:#75715e"&gt;--第6次执行时间明显变长
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_prepared_statements&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;gx &lt;span style="color:#75715e"&gt;--pg14支持pg_prepared_statements
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;generic_plans &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;custom_plans &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;前5次硬解析用custom_plans跑出来都很快，第6次用到generic_plan，走的created_date，即为生产的故障计划，非常慢。&lt;/p&gt;
&lt;p&gt;所以优化建议里用created_date是有些问题，但是替换变量为具体值后explain出来的执行计划是对的，而生产环境业务用绑定变量跑，跑到了generic plan，故障就此出现。&lt;/p&gt;

&lt;h3 class="relative group"&gt;为什么新的执行计划执行时间很长但预估rows很小？
 &lt;div id="为什么新的执行计划执行时间很长但预估rows很小" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e6%96%b0%e7%9a%84%e6%89%a7%e8%a1%8c%e8%ae%a1%e5%88%92%e6%89%a7%e8%a1%8c%e6%97%b6%e9%97%b4%e5%be%88%e9%95%bf%e4%bd%86%e9%a2%84%e4%bc%b0rows%e5%be%88%e5%b0%8f" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;故障执行计划有个问题，预估的cost太小，rows太少&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_lzltab_202501_created_date &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzltab_202501 cc_1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;1450&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;59&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8958&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;66&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((created_date &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (created_date &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这从业务逻辑上看这有点不正常，因为create_date条件已经跨了多个分区，created_date是分区键，那么where created&amp;gt;=xx &amp;lt;=yy一定是连续的，在子分区上的选择率应该始终为1，rows应是子分区行数，应该是几百万而不是几千。&lt;/p&gt;
&lt;p&gt;刚开始以为是统计信息的问题，但统计信息是比较准确的，202501的历史分区数据没有什么变动。&lt;/p&gt;
&lt;p&gt;既然是generic plan需要从generic plan预估代价入手翻源码。cost要难一点，看rows的预估逻辑要相对简单些，也容易定位。&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;double&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;calc_rangesel&lt;/span&gt;(TypeCacheEntry &lt;span style="color:#f92672"&gt;*&lt;/span&gt;typcache, VariableStatData &lt;span style="color:#f92672"&gt;*&lt;/span&gt;vardata,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			 &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; RangeType &lt;span style="color:#f92672"&gt;*&lt;/span&gt;constval, Oid operator)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/* with any other operator, empty Op non-empty matches nothing */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			selec &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;1.0&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; empty_frac) &lt;span style="color:#f92672"&gt;*&lt;/span&gt; hist_selec;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/* all range operators are strict */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	selec &lt;span style="color:#f92672"&gt;*=&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;1.0&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; null_frac);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;range_select=(1-null率)*直方图选择率&lt;/code&gt;，range直方图选择率看range命中的直方图对应的选择率再加个命中的MCV即可。不过这个案例不用算这些。&lt;/p&gt;
&lt;p&gt;因为generic plan不看直方图：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * rangesel -- restriction selectivity for range operators
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Datum
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;rangesel&lt;/span&gt;(PG_FUNCTION_ARGS)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * If we got a valid constant on one side of the operator, proceed to
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * estimate using statistics. Otherwise punt and return a default constant
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * estimate. Note that calc_rangesel need not handle
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * OID_RANGE_ELEM_CONTAINED_OP.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (constrange)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		selec &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;calc_rangesel&lt;/span&gt;(typcache, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;vardata, constrange, operator);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		selec &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;default_range_selectivity&lt;/span&gt;(operator);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;calc_rangesel&lt;/code&gt;就是上面那个有常量值传入的选择率计算，else就是默认选择率函数&lt;code&gt;default_range_selectivity&lt;/code&gt;，不传入常量&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Returns a default selectivity estimate for given operator, when we don&amp;#39;t
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * have statistics or cannot use them for some reason.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;double&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;default_range_selectivity&lt;/span&gt;(Oid operator)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; (operator)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; OID_RANGE_CONTAINS_ELEM_OP:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; OID_RANGE_ELEM_CONTAINED_OP:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * &amp;#34;range @&amp;gt; elem&amp;#34; is more or less identical to a scalar
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * inequality &amp;#34;A &amp;gt;= b AND A &amp;lt;= c&amp;#34;.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; DEFAULT_RANGE_INEQ_SEL;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;range的默认选择率define：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/* default selectivity estimate for range inequalities &amp;#34;A &amp;gt; b AND A &amp;lt; c&amp;#34; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define DEFAULT_RANGE_INEQ_SEL	0.005&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;返回生产环境计算rows&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; reltuples::bigint&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;005&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_class &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; relname&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;lzltab_202501&amp;#39;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;gx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;[ RECORD &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; ]&lt;span style="color:#75715e"&gt;------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;?&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;column&lt;/span&gt;&lt;span style="color:#f92672"&gt;?&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8958&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;350&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这跟实际的rows估算值8958相等：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;idx_lzltab_202501_created_date &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzltab_202501 cc_1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;1450&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;59&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8958&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;66&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;所以新的执行计划估算不准确是因为generic plan使用了默认的选择率。&lt;/p&gt;

&lt;h2 class="relative group"&gt;问题总结
 &lt;div id="问题总结" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e6%80%bb%e7%bb%93" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;为什么要有generic plan以及软解析的问题
 &lt;div id="为什么要有generic-plan以及软解析的问题" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e6%9c%89generic-plan%e4%bb%a5%e5%8f%8a%e8%bd%af%e8%a7%a3%e6%9e%90%e7%9a%84%e9%97%ae%e9%a2%98" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;把generic plan看成是DEFAULT estimate plan还更容易理解一点&lt;/p&gt;
&lt;p&gt;为什么generic plan好像总是有问题？&lt;/p&gt;
&lt;p&gt;理出以下思维链：&lt;/p&gt;
&lt;p&gt;generic plan是为了减少硬解析，即使用软解析
如果不是每次执行都是硬解析，那么可以不传入具体参数直接使用执行计划
如果不传参直接用执行计划，那么需要提前生成执行计划&lt;/p&gt;
&lt;p&gt;提前生成执行计划的方式：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不传参执行计划（generic plan）&lt;/li&gt;
&lt;li&gt;用前几次传参生成的执行计划（pg没有这种东西）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果使用generic plan，有可能是不准确的，比如&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1.数据倾斜（如某个mcv极高，如where a=1，但a=1非常多），这极度依赖传入参数本身是啥，但generic plan不传参，所以执行计划不可能准确&lt;/li&gt;
&lt;li&gt;2.数据均衡但无法准确计算选择率（如where a&amp;gt;$1 and a&amp;lt;$2），如果不知道range没人能计算出选择率，但generic plan不传参，所以执行计划不可能准确&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果前几次传参执行计划（pg没有这种东西），有可能也是不准确的，比如&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;数据倾斜，前几次传参没有普遍性，前几次传参极大的影响了后续固定的执行计划是什么&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;generic plan预估不准的问题分类
 &lt;div id="generic-plan预估不准的问题分类" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#generic-plan%e9%a2%84%e4%bc%b0%e4%b8%8d%e5%87%86%e7%9a%84%e9%97%ae%e9%a2%98%e5%88%86%e7%b1%bb" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;因为要5次对比，所以generic plan的问题可以分为2种：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;前5次SQL的执行没有普遍性。跟前5次执行计划相关性大，依赖数据倾斜和前5次参数是否具有普遍性。&lt;/li&gt;
&lt;li&gt;generic plan本身有问题。generic plan因为数据倾斜或数据均衡但无法准确计算选择率，导致generic plan本身执行效率低下&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 class="relative group"&gt;优化方案
 &lt;div id="优化方案" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%bc%98%e5%8c%96%e6%96%b9%e6%a1%88" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;从这个案例看下来，generic plan问题在分区表上可能会出现，分区键是连续的，扫描所有分区建选择率应该为1，但generic plan为0.05，很可能导致走“全索引”扫描这种场景。&lt;/p&gt;
&lt;p&gt;所以在优化的时候需要考虑更多：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不要建太多索引迷惑优化器&lt;/li&gt;
&lt;li&gt;排除generic plan的干扰。用&lt;code&gt;EXECUTE&lt;/code&gt;真实跑6次&lt;/li&gt;
&lt;li&gt;会话级别&lt;code&gt;set plan_cache_mode='force_generic_plan'&lt;/code&gt;; or &lt;code&gt;set plan_cache_mode='force_custom_plan';&lt;/code&gt;对比执行计划；或者在pg16+用explain (GENERIC_PLAN)对比执行计划&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;语法参考：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--prepare/excute
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;PREPARE&lt;/span&gt; sql1(text) &lt;span style="color:#66d9ef"&gt;AS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;COUNT&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; LZL &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;EXECUTE&lt;/span&gt; sql1(&lt;span style="color:#e6db74"&gt;&amp;#39;zzz&amp;#39;&lt;/span&gt;); &lt;span style="color:#75715e"&gt;--跑6次再说
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;EXPLAIN&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;EXECUTE&lt;/span&gt; sql1(&lt;span style="color:#e6db74"&gt;&amp;#39;zzz&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_prepared_statements &lt;span style="color:#75715e"&gt;--查看prepare语句信息，只能看当前会话
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--对比执行计划，设置会话参数后执行EXPLAIN EXECUTE
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; plan_cache_mode&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;force_generic_plan&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; plan_cache_mode&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;force_custom_plan&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--直接查看genetic plan,16+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; (GENERIC_PLAN) xx &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded></item><item><title>案例-授权和walsender跑不动</title><link>https://lastdba.com/2025/06/26/%E6%A1%88%E4%BE%8B-%E6%8E%88%E6%9D%83%E5%92%8Cwalsender%E8%B7%91%E4%B8%8D%E5%8A%A8/</link><pubDate>Thu, 26 Jun 2025 00:00:00 +0000</pubDate><guid>https://lastdba.com/2025/06/26/%E6%A1%88%E4%BE%8B-%E6%8E%88%E6%9D%83%E5%92%8Cwalsender%E8%B7%91%E4%B8%8D%E5%8A%A8/</guid><description>&lt;h2 class="relative group"&gt;现象
 &lt;div id="现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;walsender LSN未推进，堆栈显示堵在pathman的&lt;code&gt;invalidate_psin_entries_using_relid&lt;/code&gt;，relid改变，walsender cpu打满。&lt;/p&gt;</description><content:encoded>
&lt;h2 class="relative group"&gt;现象
 &lt;div id="现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;walsender LSN未推进，堆栈显示堵在pathman的&lt;code&gt;invalidate_psin_entries_using_relid&lt;/code&gt;，relid改变，walsender cpu打满。&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pstack &lt;span style="color:#ae81ff"&gt;121327&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; hash_seq_search (status&lt;span style="color:#f92672"&gt;=&lt;/span&gt;status&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x7fffaadf8330) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; dynahash.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;1441&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x00002ba3b40ec728 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; invalidate_psin_entries_using_relid (relid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;relid&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;42319501&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; src&lt;span style="color:#f92672"&gt;/&lt;/span&gt;relation_info.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;251&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x00002ba3b40ecb3d &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; forget_status_of_relation (relid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;relid&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;42319501&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; src&lt;span style="color:#f92672"&gt;/&lt;/span&gt;relation_info.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;232&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x00002ba3b40fcc96 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; pathman_relcache_hook (arg&lt;span style="color:#f92672"&gt;=&amp;lt;&lt;/span&gt;optimized &lt;span style="color:#66d9ef"&gt;out&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;, relid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;42319501&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; src&lt;span style="color:#f92672"&gt;/&lt;/span&gt;hooks.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;934&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x000000000087168a &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; LocalExecuteInvalidationMessage (msg&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x3a391c8) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; inval.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;595&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x000000000071d50e &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; ReorderBufferExecuteInvalidations (rb&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x1b63ff8, txn&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x1be5f58, txn&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x1be5f58) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; reorderbuffer.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;2238&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; ReorderBufferCommit (rb&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x1b63ff8, xid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;xid&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4285897514&lt;/span&gt;, commit_lsn&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;405674661986920&lt;/span&gt;, end_lsn&lt;span style="color:#f92672"&gt;=&amp;lt;&lt;/span&gt;optimized &lt;span style="color:#66d9ef"&gt;out&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;, commit_time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;commit_time&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;799377897828299&lt;/span&gt;, origin_id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;origin_id&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, origin_lsn&lt;span style="color:#f92672"&gt;=&lt;/span&gt;origin_lsn&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; reorderbuffer.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;1819&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;7&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x0000000000712d18 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; DecodeCommit (xid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4285897514&lt;/span&gt;, parsed&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x7fffaadf8630, buf&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x7fffaadf87f0, ctx&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x1a359e8) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; decode.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;637&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; DecodeXactOp (ctx&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x1a359e8, buf&lt;span style="color:#f92672"&gt;=&lt;/span&gt;buf&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x7fffaadf87f0) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; decode.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;245&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x00000000007130b2 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; LogicalDecodingProcessRecord (ctx&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x1a359e8, record&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x1a35c80) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; decode.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;114&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x0000000000733662 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; XLogSendLogical () &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; walsender.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;2885&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;11&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x0000000000735942 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; WalSndLoop (send_data&lt;span style="color:#f92672"&gt;=&lt;/span&gt;send_data&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x733620 &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;XLogSendLogical&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; walsender.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;2287&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x0000000000736692 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; StartLogicalReplication (cmd&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x1846c68) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; walsender.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;1213&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;13&lt;/span&gt; exec_replication_command (cmd_string&lt;span style="color:#f92672"&gt;=&lt;/span&gt;cmd_string&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x181a288 &lt;span style="color:#e6db74"&gt;&amp;#34;START_REPLICATION SLOT \&amp;#34;&lt;/span&gt;lzl_logical_rep&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34; LOGICAL 170F5/7C3EAE78 (\&amp;#34;&lt;/span&gt;proto_version&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34; &amp;#39;1&amp;#39;, \&amp;#34;&lt;/span&gt;publication_names&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34; &amp;#39;lzl_logical_rep&amp;#39;)&amp;#34;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; walsender.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;1640&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x0000000000774e91 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; PostgresMain (argc&lt;span style="color:#f92672"&gt;=&amp;lt;&lt;/span&gt;optimized &lt;span style="color:#66d9ef"&gt;out&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;, argv&lt;span style="color:#f92672"&gt;=&lt;/span&gt;argv&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x1866478, dbname&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x18662b8 &lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;, username&lt;span style="color:#f92672"&gt;=&amp;lt;&lt;/span&gt;optimized &lt;span style="color:#66d9ef"&gt;out&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; postgres.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;4325&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x0000000000485989 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; BackendRun (port&lt;span style="color:#f92672"&gt;=&amp;lt;&lt;/span&gt;optimized &lt;span style="color:#66d9ef"&gt;out&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;, port&lt;span style="color:#f92672"&gt;=&amp;lt;&lt;/span&gt;optimized &lt;span style="color:#66d9ef"&gt;out&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; postmaster.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;4526&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; BackendStartup (port&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x18635b0) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; postmaster.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;4210&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;17&lt;/span&gt; ServerLoop () &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; postmaster.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;1739&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x0000000000702f08 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; PostmasterMain (argc&lt;span style="color:#f92672"&gt;=&lt;/span&gt;argc&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, argv&lt;span style="color:#f92672"&gt;=&lt;/span&gt;argv&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x1814da0) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; postmaster.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;1412&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;19&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x000000000048660a &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; main (argc&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, argv&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x1814da0) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; main.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;210&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;##&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;第二次执行，堆栈一致，&lt;/span&gt;relid改变
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pstack &lt;span style="color:#ae81ff"&gt;121327&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; hash_seq_search (status&lt;span style="color:#f92672"&gt;=&lt;/span&gt;status&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x7fffaadf8330) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; dynahash.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;1441&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x00002ba3b40ec728 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; invalidate_psin_entries_using_relid (relid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;relid&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;26560221&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; src&lt;span style="color:#f92672"&gt;/&lt;/span&gt;relation_info.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;251&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x00002ba3b40ecb3d &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; forget_status_of_relation (relid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;relid&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;26560221&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; src&lt;span style="color:#f92672"&gt;/&lt;/span&gt;relation_info.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;232&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x00002ba3b40fcc96 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; pathman_relcache_hook (arg&lt;span style="color:#f92672"&gt;=&amp;lt;&lt;/span&gt;optimized &lt;span style="color:#66d9ef"&gt;out&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;, relid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;26560221&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; src&lt;span style="color:#f92672"&gt;/&lt;/span&gt;hooks.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;934&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x000000000087168a &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; LocalExecuteInvalidationMessage (msg&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x39f1f68) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; inval.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;595&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 class="relative group"&gt;分析
 &lt;div id="分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;relid改变说明walsender还在跑还没有死。LSN没有改变，可以分析LSN的位置，看看这个事务在做什么。&lt;/p&gt;
&lt;p&gt;当时的信息还在的话，可以通过slot视图查restart LSN反查wal的位置。如果当时的信息不在，可以通过stack中的LSN来找到wal日志是哪个。&lt;/p&gt;
&lt;p&gt;pg_waldump查看wal日志信息，过滤xid&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rmgr: Heap len &lt;span style="color:#f92672"&gt;(&lt;/span&gt;rec/tot&lt;span style="color:#f92672"&gt;)&lt;/span&gt;: 961/ 961, tx: 4285897514, lsn: 170F5/7DFE3470, prev 170F5/7DFE3430, desc: UPDATE+INIT off &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; xmax &lt;span style="color:#ae81ff"&gt;4285897514&lt;/span&gt; flags 0x00 ; new off &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; xmax 0, blkref &lt;span style="color:#75715e"&gt;#0: rel 1663/17662/1259 blk 8443, blkref #1: rel 1663/17662/1259 blk 7327&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rmgr: Transaction len &lt;span style="color:#f92672"&gt;(&lt;/span&gt;rec/tot&lt;span style="color:#f92672"&gt;)&lt;/span&gt;: 1778325/1778325, tx: 4285897514, lsn: 170F5/7E1F4268, prev 170F5/7E1F4220, desc: COMMIT 2025-05-01 09:24:57.828299 CST; inval msgs: catcache &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt; catcache &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt; catcache &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt; catcache &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt; catcache &lt;span style="color:#ae81ff"&gt;50&lt;/span&gt; catcache &lt;span style="color:#ae81ff"&gt;49&lt;/span&gt; catcache &lt;span style="color:#ae81ff"&gt;50&lt;/span&gt; catcache &lt;span style="color:#ae81ff"&gt;49&lt;/span&gt; catcache &lt;span style="color:#ae81ff"&gt;50&lt;/span&gt; catcache &lt;span style="color:#ae81ff"&gt;49&lt;/span&gt; catcache &lt;span style="color:#ae81ff"&gt;50&lt;/span&gt; catcache &lt;span style="color:#ae81ff"&gt;49&lt;/span&gt; catcache &lt;span style="color:#ae81ff"&gt;50&lt;/span&gt; catcache &lt;span style="color:#ae81ff"&gt;49&lt;/span&gt; catcache &lt;span style="color:#ae81ff"&gt;50&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; relcache &lt;span style="color:#ae81ff"&gt;48813261&lt;/span&gt; relcache &lt;span style="color:#ae81ff"&gt;48813255&lt;/span&gt; relcache &lt;span style="color:#ae81ff"&gt;51030741&lt;/span&gt; relcache &lt;span style="color:#ae81ff"&gt;48813252&lt;/span&gt; relcache &lt;span style="color:#ae81ff"&gt;50737247&lt;/span&gt; relcache &lt;span style="color:#ae81ff"&gt;48813246&lt;/span&gt; relcache &lt;span style="color:#ae81ff"&gt;48813243&lt;/span&gt; relcache &lt;span style="color:#ae81ff"&gt;48813237&lt;/span&gt; relcache &lt;span style="color:#ae81ff"&gt;50737241&lt;/span&gt; relcache &lt;span style="color:#ae81ff"&gt;48813234&lt;/span&gt; relcache &lt;span style="color:#ae81ff"&gt;48813224&lt;/span&gt; relcache &lt;span style="color:#ae81ff"&gt;49379811&lt;/span&gt; relcache &lt;span style="color:#ae81ff"&gt;48813216&lt;/span&gt; relcache &lt;span style="color:#ae81ff"&gt;48813210&lt;/span&gt; relcache &lt;span style="color:#ae81ff"&gt;45452775&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;rel 1663/17662/1259的record有18万条，最后一条record是inval msgs，catcache有7万，relcache 3万。&lt;/p&gt;
&lt;p&gt;rel 1663/17662/1259是pg_class，通过xmin去查pg_class可以找到对应的表和xid提交时间：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; xmin,xmax,pg_xact_commit_timestamp(xmin),relname &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_class &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; xmin&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;4285897514&amp;#39;&lt;/span&gt;::xid &lt;span style="color:#66d9ef"&gt;order&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;by&lt;/span&gt; relname &lt;span style="color:#66d9ef"&gt;desc&lt;/span&gt; ;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; xmin &lt;span style="color:#f92672"&gt;|&lt;/span&gt; xmax &lt;span style="color:#f92672"&gt;|&lt;/span&gt; pg_xact_commit_timestamp &lt;span style="color:#f92672"&gt;|&lt;/span&gt; relname 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;------------+------+-------------------------------+---------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;4285897514&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2025&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;57&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;828299&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; v$session
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;4285897514&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2025&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;57&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;828299&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; tmp_20230801_id_seq
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;4285897514&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2025&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;57&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;828299&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; tmp_20230801
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;4285897514&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2025&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;57&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;828299&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; test_param
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;4285897514&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2025&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;57&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;828299&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; test_20240105
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_class &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; xmin&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;4285897514&amp;#39;&lt;/span&gt;::xid ;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;18523&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_class ;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;139138&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;通过时间去查pglog日志：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2025-05-01 09:24:59.837 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;postgres&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,61418,&lt;span style="color:#e6db74"&gt;&amp;#34;[local]&amp;#34;&lt;/span&gt;,6812cd65.efea,3,&lt;span style="color:#e6db74"&gt;&amp;#34;DO&amp;#34;&lt;/span&gt;,2025-05-01 09:24:53 CST,549/0,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;duration: 6036.275 ms statement: 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; EXECUTE &amp;#39;GRANT SELECT ON ALL TABLES IN SCHEMA public TO r_lzldbdata_qry&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; END;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &lt;/span&gt;$$&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;psql&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;client backend&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;基本可以定位是这个授权引起，因为授权会更新pgclass中的relacl，至少更新了1.8w个relation的权限，pgclass更新会触发invalidation消息，大量的invalidation消息在walsender进程中处理缓慢。&lt;/p&gt;

&lt;h2 class="relative group"&gt;复现
 &lt;div id="复现" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%a4%8d%e7%8e%b0" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--建逻辑复制链路，随便来个
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; pg_create_logical_replication_slot(&lt;span style="color:#e6db74"&gt;&amp;#39;logical_test&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;test_decoding&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pg_recvlogical &lt;span style="color:#f92672"&gt;-&lt;/span&gt;h &lt;span style="color:#ae81ff"&gt;127&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;p &lt;span style="color:#ae81ff"&gt;7997&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;d lzldb &lt;span style="color:#f92672"&gt;-&lt;/span&gt;U repuser &lt;span style="color:#75715e"&gt;--slot=logical_test --start -f recv.sql &amp;amp;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--建多张表
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;DO&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$$&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;BEGIN&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;FOR&lt;/span&gt; i &lt;span style="color:#66d9ef"&gt;IN&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;20000&lt;/span&gt; LOOP
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;EXECUTE&lt;/span&gt; format(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;CREATE TABLE IF NOT EXISTS table_%s ( 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; col1 varchar(10)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; )&amp;#39;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; lpad(i::text, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;-- 生成5位数字编号的表名
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;END&lt;/span&gt; LOOP;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;END&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$$&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--一次授权
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;grant&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;all&lt;/span&gt; tables &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;schema&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; r_lzldb_qry;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--完美复现
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;postgres&lt;span style="color:#f92672"&gt;@&lt;/span&gt;lzlhost:&lt;span style="color:#f92672"&gt;~/&lt;/span&gt;lzl&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;grant&lt;/span&gt;]&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt; pstack &lt;span style="color:#ae81ff"&gt;172862&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; hash_seq_search (status&lt;span style="color:#f92672"&gt;=&lt;/span&gt;status&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x7ffd664be280) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; dynahash.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;1444&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x00002ad31235e728 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; invalidate_psin_entries_using_relid (relid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;relid&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1002857&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; src&lt;span style="color:#f92672"&gt;/&lt;/span&gt;relation_info.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;251&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x00002ad31235eb3d &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; forget_status_of_relation (relid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;relid&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1002857&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; src&lt;span style="color:#f92672"&gt;/&lt;/span&gt;relation_info.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;232&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x00002ad31236ec96 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; pathman_relcache_hook (arg&lt;span style="color:#f92672"&gt;=&amp;lt;&lt;/span&gt;optimized &lt;span style="color:#66d9ef"&gt;out&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;, relid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1002857&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; src&lt;span style="color:#f92672"&gt;/&lt;/span&gt;hooks.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;934&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x000000000087168a &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; LocalExecuteInvalidationMessage (msg&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x2ad3c3f61a88) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; inval.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;595&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x000000000071d50e &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; ReorderBufferExecuteInvalidations (rb&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x17e5698, txn&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x180d698, txn&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x180d698) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; reorderbuffer.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;2238&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[postgres&lt;span style="color:#f92672"&gt;@&lt;/span&gt;lzlhost:&lt;span style="color:#f92672"&gt;~/&lt;/span&gt;lzl&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;grant&lt;/span&gt;]&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt; pstack &lt;span style="color:#ae81ff"&gt;172862&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x0000000000891d0c &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; hash_seq_search (status&lt;span style="color:#f92672"&gt;=&lt;/span&gt;status&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x7ffd664be280) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; dynahash.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;1441&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x00002ad31235e728 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; invalidate_psin_entries_using_relid (relid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;relid&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1011110&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; src&lt;span style="color:#f92672"&gt;/&lt;/span&gt;relation_info.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;251&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x00002ad31235eb3d &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; forget_status_of_relation (relid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;relid&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1011110&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; src&lt;span style="color:#f92672"&gt;/&lt;/span&gt;relation_info.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;232&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x00002ad31236ec96 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; pathman_relcache_hook (arg&lt;span style="color:#f92672"&gt;=&amp;lt;&lt;/span&gt;optimized &lt;span style="color:#66d9ef"&gt;out&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;, relid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1011110&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; src&lt;span style="color:#f92672"&gt;/&lt;/span&gt;hooks.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;934&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--relid在动
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--cpu打满:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ps &lt;span style="color:#f92672"&gt;-&lt;/span&gt;eo pid,&lt;span style="color:#f92672"&gt;%&lt;/span&gt;cpu,&lt;span style="color:#f92672"&gt;%&lt;/span&gt;mem&lt;span style="color:#f92672"&gt;|&lt;/span&gt;grep &lt;span style="color:#ae81ff"&gt;172862&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;172862&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;99&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--运行2h左右追平&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 class="relative group"&gt;without pathman加速walsender解析
 &lt;div id="without-pathman加速walsender解析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#without-pathman%e5%8a%a0%e9%80%9fwalsender%e8%a7%a3%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;因为库里面是没有用pathman分区表的，但有pathman extension，所以尝试绕过pathman hook以加速walsender解析过程。&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;drop&lt;/span&gt; extension pg_pathman;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;grant&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;update&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;all&lt;/span&gt; tables &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;schema&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; r_lzldb_upd;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[postgres&lt;span style="color:#f92672"&gt;@&lt;/span&gt;lzlhost&lt;span style="color:#f92672"&gt;~/&lt;/span&gt;lzl&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;grant&lt;/span&gt;]&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt; pstack &lt;span style="color:#ae81ff"&gt;133460&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; hash_seq_search (status&lt;span style="color:#f92672"&gt;=&lt;/span&gt;status&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x7ffe292d5c90) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; dynahash.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;1418&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x000000000087f228 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; RelfilenodeMapInvalidateCallback (arg&lt;span style="color:#f92672"&gt;=&amp;lt;&lt;/span&gt;optimized &lt;span style="color:#66d9ef"&gt;out&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;, relid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1034036&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; relfilenodemap.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x000000000087168a &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; LocalExecuteInvalidationMessage (msg&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x2b9699795768) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; inval.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;595&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x000000000071d50e &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; ReorderBufferExecuteInvalidations (rb&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x195a358, txn&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x1a6ff38, txn&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x1a6ff38) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; reorderbuffer.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;2238&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; ReorderBufferCommit (rb&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x195a358, xid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;xid&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;328684387&lt;/span&gt;, commit_lsn&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8016890875224&lt;/span&gt;, end_lsn&lt;span style="color:#f92672"&gt;=&amp;lt;&lt;/span&gt;optimized &lt;span style="color:#66d9ef"&gt;out&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;, commit_time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;commit_time&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;799851538975691&lt;/span&gt;, origin_id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;origin_id&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, origin_lsn&lt;span style="color:#f92672"&gt;=&lt;/span&gt;origin_lsn&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; reorderbuffer.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;1819&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;##&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;s以内完成&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;没有注释&lt;code&gt;shared_preload_libraries&lt;/code&gt;中的&lt;code&gt;pg_pathman&lt;/code&gt;，同样有很好的效果，walsender从2小时缩短到20s。&lt;/p&gt;
&lt;p&gt;这里感觉挺奇怪，没有注释&lt;code&gt;shared_preload_libraries&lt;/code&gt;，hook应该还是要走的。分析源码发现，之所以有效果是因为hook的第一步就有pathman config表的判断，不会再走pathman中的invalidate逻辑了，所以很快可以执行完成：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Invalidate PartRelationInfo cache entry if needed.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;pathman_relcache_hook&lt;/span&gt;(Datum arg, Oid relid)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	Oid pathman_config_relid;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/* See cook_partitioning_expression() */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;pathman_hooks_enabled)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;IsPathmanReady&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * Invalidation event for PATHMAN_CONFIG table (probably DROP EXTENSION).
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * Digging catalogs here is expensive and probably illegal, so we take
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * cached relid. It is possible that we don&amp;#39;t know it atm (e.g. pathman
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * was disabled). However, in this case caches must have been cleaned
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * on disable, and there is no DROP-specific additional actions.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	pathman_config_relid &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;get_pathman_config_relid&lt;/span&gt;(true);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (relid &lt;span style="color:#f92672"&gt;==&lt;/span&gt; pathman_config_relid)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;delay_pathman_shutdown&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/* Invalidation event for some user table */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (relid &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; FirstNormalObjectId)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* Invalidate PartBoundInfo entry if needed */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;forget_bounds_of_rel&lt;/span&gt;(relid);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* Invalidate PartStatusInfo entry if needed */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;forget_status_of_relation&lt;/span&gt;(relid);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* Invalidate PartParentInfo entry if needed */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;forget_parent_of_partition&lt;/span&gt;(relid);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;get_pathman_config_relid&lt;/code&gt;获取了pathman_config表，&lt;code&gt;drop extension pg_pathman&lt;/code&gt;把db中pathman_config表删掉了，所以源码就不会走forget那一堆逻辑。&lt;/p&gt;
&lt;p&gt;也有其他办法可以加速walsender解析，比如将&lt;code&gt;pg_pathman.enable=off&lt;/code&gt;，会走&lt;code&gt;if (!IsPathmanReady())&lt;/code&gt;直接&lt;code&gt;return&lt;/code&gt;。或者最直接的注释&lt;code&gt;shared_preload_libraries&lt;/code&gt;中的&lt;code&gt;pg_pathman&lt;/code&gt;并重启实例（这是实例级不是db级）。&lt;/p&gt;

&lt;h2 class="relative group"&gt;pg14的提升
 &lt;div id="pg14的提升" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#pg14%e7%9a%84%e6%8f%90%e5%8d%87" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;pg14.0 release note:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Allow logical decoding to more efficiently process cache invalidation messages (Dilip Kumar) This allows logical decoding to work efficiently in presence of a large amount of DDL.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href="https://www.postgresql.org/docs/release/14.0/" target="_blank" rel="noreferrer"&gt;https://www.postgresql.org/docs/release/14.0/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;patch:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=d7eb52d71" target="_blank" rel="noreferrer"&gt;https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=d7eb52d71&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;pg14&lt;code&gt;ReorderBufferAddInvalidations&lt;/code&gt;的注释：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;We require to record it in form of the change so that we can execute only the required invalidations instead of executing all the invalidations on each CommandId increment.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;对比pg14和pg13，&lt;code&gt;ReorderBufferCommit&lt;/code&gt;逻辑大改&lt;/p&gt;
&lt;p&gt;13中处理事务的逻辑直接放在commit函数里&lt;code&gt;ReorderBufferCommit&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; REORDER_BUFFER_CHANGE_INTERNAL_COMMAND_ID:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					&lt;span style="color:#a6e22e"&gt;Assert&lt;/span&gt;(change&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;data.command_id &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; InvalidCommandId);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (command_id &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; change&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;data.command_id)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						command_id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; change&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;data.command_id;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;snapshot_now&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;copied)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;							&lt;span style="color:#75715e"&gt;/* we don&amp;#39;t use the global one anymore */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;							snapshot_now &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ReorderBufferCopySnap&lt;/span&gt;(rb, snapshot_now,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;																 txn, command_id);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						snapshot_now&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;curcid &lt;span style="color:#f92672"&gt;=&lt;/span&gt; command_id;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						&lt;span style="color:#a6e22e"&gt;TeardownHistoricSnapshot&lt;/span&gt;(false);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						&lt;span style="color:#a6e22e"&gt;SetupHistoricSnapshot&lt;/span&gt;(snapshot_now, txn&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;tuplecid_hash);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;						 * Every time the CommandId is incremented, we could
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;						 * see new catalog contents, so execute all
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;						 * invalidations.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;						 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						&lt;span style="color:#a6e22e"&gt;ReorderBufferExecuteInvalidations&lt;/span&gt;(rb, txn);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;14中的主要逻辑是&lt;code&gt;ReorderBufferReplay&lt;/code&gt;-&amp;gt;&lt;code&gt;ReorderBufferProcessTXN&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;在&lt;code&gt;ReorderBufferProcessTXN&lt;/code&gt;中新增&lt;code&gt;case REORDER_BUFFER_CHANGE_INVALIDATION&lt;/code&gt;判断以执行&lt;code&gt;ReorderBufferExecuteInvalidations&lt;/code&gt;执行reorderbuffer中的invalidate&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; REORDER_BUFFER_CHANGE_INVALIDATION:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					&lt;span style="color:#75715e"&gt;/* Execute the invalidation messages locally */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					&lt;span style="color:#a6e22e"&gt;ReorderBufferExecuteInvalidations&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;													 change&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;data.inval.ninvalidations,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;													 change&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;data.inval.invalidations);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;ReorderBufferExecuteInvalidations&lt;/code&gt;之后的逻辑都差不多，没有多大变动。13对比14的&lt;code&gt;ReorderBufferCommit&lt;/code&gt;主要差异：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ReorderBufferCommit&lt;/code&gt;不再是主要process txn的函数，调用栈更深&lt;/li&gt;
&lt;li&gt;新增&lt;code&gt;case REORDER_BUFFER_CHANGE_INVALIDATION&lt;/code&gt;判断，与&lt;code&gt;REORDER_BUFFER_CHANGE_INTERNAL_COMMAND_ID&lt;/code&gt;标识区分，单独处理invalidation&lt;/li&gt;
&lt;li&gt;移除以每个command_id处理invalidation的逻辑&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;根因和解决办法
 &lt;div id="根因和解决办法" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%a0%b9%e5%9b%a0%e5%92%8c%e8%a7%a3%e5%86%b3%e5%8a%9e%e6%b3%95" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;walsender卡住的根因是有批量授权任务，导致pg_class多个元组更新，触发大量invalidation消息。&lt;code&gt;GRANT privs ON ALL TABLES IN SCHEMA public TO role1&lt;/code&gt; 这样的授权语句在pg中是1个事务多个command处理的，而pg13 逻辑复制处理invalidation message时，会通过每个command去处理一次reorder buffer invalidate，并处理各个hook的inval hash表。在这个场景中，pathman hook在处理inval hash表较慢，从而导致复制延迟。&lt;/p&gt;
&lt;p&gt;pathman处理较慢的触发条件（且）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pg13-&lt;/li&gt;
&lt;li&gt;批量授权&lt;/li&gt;
&lt;li&gt;安装了pathman extension（无论是否使用）&lt;/li&gt;
&lt;li&gt;逻辑复制链路&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;即使将pathman干掉，也会在RelfilenodeMapInvalidateCallback等函数上花较多cpu。pg13目前测下来，有pathman对比没有pathman，处理时间是小时级和分钟级的差距。&lt;/p&gt;
&lt;p&gt;其他未测试但社区提及的场景（且）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pg13-&lt;/li&gt;
&lt;li&gt;批量DDL/TRUNCATE/DCL/DROP PUBLICATION&lt;/li&gt;
&lt;li&gt;逻辑复制链路&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;短期解决办法：如果没有用到pathman表的，可以drop extension或者不加载pathman so；重启链路&lt;/p&gt;
&lt;p&gt;长期解决办法：升级到pg14+（已测试非常快无延迟）&lt;/p&gt;

&lt;h3 class="relative group"&gt;
 &lt;div id="" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;

&lt;h2 class="relative group"&gt;ref
 &lt;div id="ref" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#ref" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.postgresql.org/message-id/flat/17716-1fe42e7b44fc2f25%40postgresql.org" target="_blank" rel="noreferrer"&gt;https://www.postgresql.org/message-id/flat/17716-1fe42e7b44fc2f25%40postgresql.org&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=d7eb52d71" target="_blank" rel="noreferrer"&gt;https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=d7eb52d71&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>pg数据库运维经验2024</title><link>https://lastdba.com/2025/01/08/pg%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%90%E7%BB%B4%E7%BB%8F%E9%AA%8C2024/</link><pubDate>Wed, 08 Jan 2025 00:00:00 +0000</pubDate><guid>https://lastdba.com/2025/01/08/pg%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%90%E7%BB%B4%E7%BB%8F%E9%AA%8C2024/</guid><description>&lt;p&gt;这篇文章主要是讲pg运维常见问题，两三年见一次的疑难杂症就不说了。&lt;/p&gt;
&lt;p&gt;主要是技术性运维总结，主打通俗易懂和快速上手，尽量避免源码层面等深入分析。&lt;/p&gt;

&lt;h2 class="relative group"&gt;SQL性能与执行计划
 &lt;div id="sql性能与执行计划" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#sql%e6%80%a7%e8%83%bd%e4%b8%8e%e6%89%a7%e8%a1%8c%e8%ae%a1%e5%88%92" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;执行计划突变
 &lt;div id="执行计划突变" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%89%a7%e8%a1%8c%e8%ae%a1%e5%88%92%e7%aa%81%e5%8f%98" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;pg官方不支持hint功能，并且计划永远不支持！
PG社区大概是这个意思&amp;quot;我们的优化器是完美的，如果当前执行计划不够优秀，那是开发不懂优化”。&lt;/p&gt;</description><content:encoded>&lt;p&gt;这篇文章主要是讲pg运维常见问题，两三年见一次的疑难杂症就不说了。&lt;/p&gt;
&lt;p&gt;主要是技术性运维总结，主打通俗易懂和快速上手，尽量避免源码层面等深入分析。&lt;/p&gt;

&lt;h2 class="relative group"&gt;SQL性能与执行计划
 &lt;div id="sql性能与执行计划" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#sql%e6%80%a7%e8%83%bd%e4%b8%8e%e6%89%a7%e8%a1%8c%e8%ae%a1%e5%88%92" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;执行计划突变
 &lt;div id="执行计划突变" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%89%a7%e8%a1%8c%e8%ae%a1%e5%88%92%e7%aa%81%e5%8f%98" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;pg官方不支持hint功能，并且计划永远不支持！
PG社区大概是这个意思&amp;quot;我们的优化器是完美的，如果当前执行计划不够优秀，那是开发不懂优化”。&lt;/p&gt;
&lt;p&gt;不管pg社区怎么看，生产环境的执行计划突变问题是时常发生的，而且我们没有ORACLE那样原生且丰富的绑定执行计划手段来处理问题。这对生产运维来说是一个挑战，例如：某天早上，一个敏感的sql突然执行计划改变了，运行时间从0.1s上涨到1s，由于SQL有一定的并发导致数据库的cpu打满，业务感知明显。由于我们没有绑定执行计划的手段，此时我们唯二能做的快速恢复手段就是1.收集统计信息 2.scale up扩容cpu。&lt;/p&gt;
&lt;p&gt;这里的快速恢复手段有个问题是：收集统计信息一定有用吗？好的DBA可以找到优化器中的关键问题步骤在哪，但是也不能快速脑补一个完整的执行计划出来，特别是SQL比较复杂的时候。收集统计信息这个恢复手段，实际上把SQL优化问题返还给了优化器，同时相信优化器是可以胜任这个工作的。虽然这看上去有些扯，但是在PG数据库中，绝大部分情况是有用的（对于已知收集统计信息无用的场景，见&amp;quot;order by limit问题&amp;quot;小节)。&lt;/p&gt;
&lt;p&gt;为什么执行计划会突变且性能变差？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;执行计划是基于成本的，而成本又基于统计信息，统计信息又是永远滞后的&lt;/li&gt;
&lt;li&gt;SQL足够复杂的话执行路径就会有非常多种，优化器会根据成本选择最优的一条&lt;/li&gt;
&lt;li&gt;PG提供了很多优化器参数可以调整，目的是以适配本地硬件设置（如&lt;code&gt;seq_page_cost&lt;/code&gt;
,&lt;code&gt;effective_cache_size&lt;/code&gt;等等），我们可以通过调整这些参数来微调优化器的倾向。但是这些参数太底层，虽然理论上是有优化空间，但都是牵一发而动全身的。特别是数据库上线后，调整这些参数就是一个极高风险的操作。从这些参数设置的理由来看，也可以推测执行计划不可能是100%完美的，因为优化器的推理也依赖环境&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;即使强如oracle，提供了各种方案稳固执行计划，它也保证不了SQL 100%不会出问题，因为SQL、数据、统计信息、绑定变量等等都是动态的。
对于PGer来说还想不了那么远，不过我们可以尽可能地考虑稳定执行计划的方案，如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不要用太多的表连接。表越多可能的执行计划也就越多，甚至&lt;a href="https://www.postgresql.org/docs/16/geqo-pg-intro.html" target="_blank" rel="noreferrer"&gt;PG GEQO&lt;/a&gt;会放弃生成所有的执行计划，这就降低了最优执行计划的概率&lt;/li&gt;
&lt;li&gt;不要写太过复杂的SQL。还要考虑SQL可能是框架（ORM）生成而不是业务人员手工编写的，这样的SQL一般是为了实现某个目标而几乎不考虑SQL的简洁性和阅读性，优化起来十分棘手。&lt;/li&gt;
&lt;li&gt;不要乱建索引以迷惑优化器，必须有明确的目标&lt;/li&gt;
&lt;li&gt;调整表的统计信息搜集阈值&lt;code&gt;autovacuum_vacuum_scale_factor&lt;/code&gt;（参考“统计信息收集不及时”小节）&lt;/li&gt;
&lt;li&gt;可以使用pg_hint_plan来提示优化器。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;pg_hint_plan
 &lt;div id="pg_hint_plan" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#pg_hint_plan" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/ossc-db/pg_hint_plan" target="_blank" rel="noreferrer"&gt;pg_hint_plan&lt;/a&gt;是第三方插件，通过hint来提示优化器选择正确的执行计划。
&lt;strong&gt;pg_hint_plan支持：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;指定扫描方式（如索引扫描）、连接方式（NL/HASH/MERGE）、连接顺序、memoize、指定预估行数、并行、GUC参数&lt;/li&gt;
&lt;li&gt;通过hint_plan.hints绑定sql的执行计划，不需要改变业务SQL文本&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;pg_hint_plan缺陷：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;子查询、外部表、CTE、视图、PL/SQL等有使用限制&lt;/li&gt;
&lt;li&gt;compute_query_id会把hint当做注释忽略&lt;/li&gt;
&lt;li&gt;未知的bug&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这个插件虽然在持续更新，但是（我）还没有找到大规模生产应用的案例。另外我们在少量的生产应用场景中发现了一些问题，执行计划可能不会生效，这跟jdbc执行计划缓存有关系，至于有没有其他问题暂时不好下定论。
总之pg_hint_plan是个好东西，但是生产大规模部署有待商榷。推荐静待其变，可以试用但不要对它产生依赖性。&lt;/p&gt;

&lt;h3 class="relative group"&gt;统计信息收集不及时
 &lt;div id="统计信息收集不及时" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%bb%9f%e8%ae%a1%e4%bf%a1%e6%81%af%e6%94%b6%e9%9b%86%e4%b8%8d%e5%8f%8a%e6%97%b6" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;统计信息是sql优化的基础，pg统计信息并不难但还是有很多人没弄明白。&lt;/p&gt;
&lt;p&gt;pg的统计信息主要看这3个表：pg_class、pg_stat_all_tables、pg_stat&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- pg_class看pages和tuples
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; relname,relpages,reltuples::bigint &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_class &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; relname&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;lzlpg&amp;#39;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;gx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;[ RECORD &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; ]&lt;span style="color:#75715e"&gt;------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;relname &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzlpg
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;relpages &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;187501&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;reltuples &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;6000032&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--pg_stat_all_tables看活元组、死元组，上次统计信息收集时间
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; relname,n_live_tup,n_dead_tup,last_analyze,last_autoanalyze &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_stat_all_tables &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; relname&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;lzlpg&amp;#39;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;gx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;[ RECORD &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; ]&lt;span style="color:#75715e"&gt;----+------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;relname &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzlpg
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n_live_tup &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;6000032&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n_dead_tup &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;last_analyze &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2025&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;54&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;44&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;553057&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;last_autoanalyze &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--pg_stats看列的统计信息，每个字段都需要了解含义
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_stats &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; tablename&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;lzlpg&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;and&lt;/span&gt; attname&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;gx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;[ RECORD &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; ]&lt;span style="color:#75715e"&gt;----------+-------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;schemaname &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tablename &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzlpg
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;attname &lt;span style="color:#f92672"&gt;|&lt;/span&gt; a
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;inherited &lt;span style="color:#f92672"&gt;|&lt;/span&gt; f
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;null_frac &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;avg_width &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;70&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n_distinct &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;most_common_vals &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;most_common_freqs &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;histogram_bounds &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;correlation &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;most_common_elems &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;most_common_elem_freqs &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;elem_count_histogram &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;统计信息过久很有可能会造成SQL执行计划改变，引起SQL性能问题。
此时就需要查看&lt;code&gt;pg_stat_all_tables&lt;/code&gt;表的&lt;code&gt;last_autovacuum&lt;/code&gt;,&lt;code&gt;last_autoanalyze&lt;/code&gt;时间来判断表的收集是不是滞后了。&lt;/p&gt;
&lt;p&gt;为什么要调整？因为表的统计信息收集阈值&lt;code&gt;autovacuum_analyze_scale_factor&lt;/code&gt; 默认值是0.1，也就是数据变化达到10%时，才会收集统计信息。例如一个10亿数据的表，数据变化达到1亿时才会收集，频率可能太低了。&lt;/p&gt;
&lt;p&gt;应该结合是否核心业务表、SQL表连接个数、SQL复杂度、表访问频率、月初越界问题、数据倾斜问题等判断是否需要针对性的调整表的&lt;code&gt;autovacuum_vacuum_scale_factor&lt;/code&gt;,&lt;code&gt;autovacuum_analyze_scale_factor&lt;/code&gt;以提高统计信息收集频率，降低SQL执行计划突变的概率，同时也要避免收集过于频繁老是跑vacuum浪费资源。&lt;/p&gt;
&lt;p&gt;到底该调整到多少？举个例子：&lt;/p&gt;
&lt;p&gt;以月表（或月分区表）及SQL统计当天数据为例，由于&lt;code&gt;autovacuum_analyze_scale_factor =0.1&lt;/code&gt;，月表在前10天基本每天都会收集，在第12天左右的时候可能不会收集，这时候统计信息可能越界，执行计划就有可能有问题。为了保证月表在每月的10-31天都收集统计信息，应该把&lt;code&gt;autovacuum_analyze_scale_factor&lt;/code&gt;设置得小于&lt;code&gt;0.03&lt;/code&gt;，所以推荐&lt;code&gt;autovacuum_analyze_scale_factor=0.02&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;参数调整参考（请考虑表上的业务数据模型！）：&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;参数名&lt;/th&gt;
 &lt;th&gt;默认值&lt;/th&gt;
 &lt;th&gt;建议值&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;autovacuum_vacuum_scale_factor&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;0.2&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;0.04&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;autovacuum_analyze_scale_factor&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;0.1&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;0.02&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 class="relative group"&gt;优化器可能选择其他索引而不是主键
 &lt;div id="优化器可能选择其他索引而不是主键" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%bc%98%e5%8c%96%e5%99%a8%e5%8f%af%e8%83%bd%e9%80%89%e6%8b%a9%e5%85%b6%e4%bb%96%e7%b4%a2%e5%bc%95%e8%80%8c%e4%b8%8d%e6%98%af%e4%b8%bb%e9%94%ae" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;一般来说主键的过滤性已经是最高了，但是优化器可能也不会选择走主键&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--复现命令
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; t1(a char(&lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;primary&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;key&lt;/span&gt;,b char(&lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;insert&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;into&lt;/span&gt; t1 &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; md5(&lt;span style="color:#66d9ef"&gt;g&lt;/span&gt;::text),md5(&lt;span style="color:#66d9ef"&gt;g&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; generate_series(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;10000&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;g&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; idxa &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; t1(a);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; idxb &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; t1(b);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt; t1;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt;,buffers) &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; t1 &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;qwer&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;and&lt;/span&gt; b&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;qwer&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt;,buffers) &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; t1 &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;qwer&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;and&lt;/span&gt; b&lt;span style="color:#f92672"&gt;||&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;qwer&amp;#39;&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--a、b字段有同样的过滤性，但是优化器没有走主键而是走普通索引
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt;,buffers) &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; t1 &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;qwer&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;and&lt;/span&gt; b&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;qwer&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idxb &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; t1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;41&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2008&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;045&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;046&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (b &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;qwer&amp;#39;&lt;/span&gt;::bpchar)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (a &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;qwer&amp;#39;&lt;/span&gt;::bpchar)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--强行走主键，cost只多一丢丢丢
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt;,buffers) &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; t1 &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;qwer&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;and&lt;/span&gt; b&lt;span style="color:#f92672"&gt;||&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;qwer&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idxa &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; t1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;41&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;44&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2008&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;079&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;079&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (a &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;qwer&amp;#39;&lt;/span&gt;::bpchar)&lt;span style="color:#f92672"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (((b)::text &lt;span style="color:#f92672"&gt;||&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;qwer&amp;#39;&lt;/span&gt;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared &lt;span style="color:#66d9ef"&gt;read&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;虽然a、b两个字段类型和选择率是一样的，但是优化器没有选择走主键而是走了普通索引，从cost来看走主键的cost多了0.01。&lt;/p&gt;
&lt;p&gt;这有什么问题？&lt;/p&gt;
&lt;p&gt;从当前这个表数据分布来看选择普通索引问题不大，但是数据一旦变化，两个索引的执行计划效率就会有差别：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;alter&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; t1 &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; (autovacuum_enabled &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;off&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;insert&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;into&lt;/span&gt; t1 &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; md5(&lt;span style="color:#66d9ef"&gt;g&lt;/span&gt;::text),&lt;span style="color:#e6db74"&gt;&amp;#39;repeat&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; generate_series(&lt;span style="color:#ae81ff"&gt;20001&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;30000&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;g&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--b=&amp;#39;repeat&amp;#39;过滤性很差，但是还是走b字段索引
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt;,buffers) &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; t1 &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;qwer&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;and&lt;/span&gt; b&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;repeat&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idxb &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; t1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;41&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2008&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;823&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;824&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (b &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;repeat&amp;#39;&lt;/span&gt;::bpchar)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (a &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;qwer&amp;#39;&lt;/span&gt;::bpchar)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Rows&lt;/span&gt; Removed &lt;span style="color:#66d9ef"&gt;by&lt;/span&gt; Filter: &lt;span style="color:#ae81ff"&gt;10000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2511&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--对比走主键的执行计划
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt;,buffers) &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; t1 &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;qwer&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;and&lt;/span&gt; b&lt;span style="color:#f92672"&gt;||&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;repeat&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idxa &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; t1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;41&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;44&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2008&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;041&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;041&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (a &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;qwer&amp;#39;&lt;/span&gt;::bpchar)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (((b)::text &lt;span style="color:#f92672"&gt;||&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;repeat&amp;#39;&lt;/span&gt;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;即使真实的过滤性不好，优化器仍然选择走普通索引，但是走普通索引的效率要低很多，因为shared hit=2511远大于shared hit=3。如果是敏感业务sql或者数据量比较大的时候，就会有问题，这个问题在生产中也常见。
解决办法：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;手动收集统计信息；调高统计信息收集频率&lt;/li&gt;
&lt;li&gt;pg_hint_plan&lt;/li&gt;
&lt;li&gt;改写sql让其不能走普通索引&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;order by limit问题
 &lt;div id="order-by-limit问题" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#order-by-limit%e9%97%ae%e9%a2%98" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;order by limit的sql已是一个常见的问题了，网上案例和分析也比较多，这里就不详细分析了（可以参考我写这篇&lt;a href="https://github.com/liuzhilong62/blogs/blob/main/PostgreSQL%E6%A1%88%E4%BE%8B/ORDER%20BY%20limit%2010%E6%AF%94ORDER%20BY%20limit%20100%E6%9B%B4%E6%85%A2.md" target="_blank" rel="noreferrer"&gt;ORDER BY limit 10比ORDER BY limit 100更慢&lt;/a&gt;)。
根本原因在于优化器目前无法评估数据以索引顺序存放在表的哪个位置，可能数据靠后而导致扫描过多的数据才返回limit。注意这个场景不是仅出现在order by limit，任何可以用到排序操作的+limit都可能有这个问题，如：group by +limit、distinct +limit、merge..&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决办法：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SQL改造：添加表达式防止走到排序列的索引上（含主键），如 &lt;code&gt;order by ''||col1 limit xxx&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;创建复合索引：创建排序字段的索引字段的复合索引，优化器可能会选择这个索引，效率一般都比排序字段的索引高。这个方案也不用动sql。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;表膨胀
 &lt;div id="表膨胀" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%a1%a8%e8%86%a8%e8%83%80" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;某个东西阻止了死元组回收
 &lt;div id="某个东西阻止了死元组回收" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%9f%90%e4%b8%aa%e4%b8%9c%e8%a5%bf%e9%98%bb%e6%ad%a2%e4%ba%86%e6%ad%bb%e5%85%83%e7%bb%84%e5%9b%9e%e6%94%b6" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;抛开autovacuum配置问题和一些边缘场景，常见的阻塞是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;长事务。注意：不是同一个表的长事务也会阻止死元组回收；查询语句也会造成这个问题&lt;/li&gt;
&lt;li&gt;复制槽。复制槽延迟和死的复制槽会造成这个问题&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这两种常见都是比较好解决的，1.terminate长事务会话 2.删除复制槽或者让消费端分析消费为什么这么慢。&lt;/p&gt;

&lt;h3 class="relative group"&gt;update并发高导致表膨胀
 &lt;div id="update并发高导致表膨胀" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#update%e5%b9%b6%e5%8f%91%e9%ab%98%e5%af%bc%e8%87%b4%e8%a1%a8%e8%86%a8%e8%83%80" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;不同于某个东西阻止vacuum回收死元组，频繁的update导致表膨胀是因为死元组生成的速度快于vacuum回收的速度。一般来说这个场景的表的&lt;code&gt;pg_stat_all_tables.n_tup_upd&lt;/code&gt;比较高，如果是因为表膨胀问题发现需要做repack的话，最好同时评估下是不是表的写入量大，应避免反复的手工repack。此时就需要调整表/索引的fillfactor参数。&lt;/p&gt;
&lt;p&gt;原理参考这篇文章&lt;a href="https://github.com/liuzhilong62/blogs/blob/main/PostgreSQL%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90/%E4%BB%8E%E5%BE%88%E6%85%A2%E7%9A%84%E5%94%AF%E4%B8%80%E7%B4%A2%E5%BC%95%E6%89%AB%E6%8F%8F%E5%88%B0%E7%B4%A2%E5%BC%95%E8%86%A8%E8%83%80.md" target="_blank" rel="noreferrer"&gt;从很慢的唯一索引扫描到索引膨胀&lt;/a&gt;，结论我直接copy下来：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;fillfactor原理：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;fillfactor相当于表或索引的水位线，在INSERT数据时，插入到page的fillfactor线就到下一页去插入。fillfactor本身是为了给update留一定的空间，防止update频繁的去寻找新的page。&lt;/p&gt;
&lt;p&gt;虽然表和索引都有fillfactor，他们的目的是一样的（为了update），但是具体细节有很大区别：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;表：如果表的某个page上还有留有空间，那么update可以在这个page中进行，不需要申请新的page或者到其他有空闲空间的page上去。不仅如此，因为PG 独有的HOT特性，页内更新不会更新索引，当然也就会减缓索引膨胀&lt;/li&gt;
&lt;li&gt;索引：不同的数据行或者相同数据行的页外更新，会新生成索引条目。fillfactor给索引页留下余量，会极大的减缓索引分离问题。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;当然，fillfactor的设置跟业务模型是息息相关的，如果数据类似日志那样是递增且完全没有更新的，那么表和索引的fillfactor设置成100无可厚非。但是大部分业务表总是有更新的，表和索引fillfactor就不应该设置成100，如果是频繁的update，那么fillfactor应该设置得更低。
然而，pg默认的fillfactor如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;表默认 fillfactor=100&lt;/li&gt;
&lt;li&gt;索引默认 fillfactor=90&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;推荐设置：&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;alter&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; lzlpg &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; (fillfactor&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;60&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;alter&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; lzlpg_pkey &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; (fillfactor&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;70&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--以上命令只会对新page生效，对存量page需要做repack
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--repack:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;.&lt;span style="color:#960050;background-color:#1e0010"&gt;检查是否有长事务，有则先处理长事务&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;.nohup pg_repack &lt;span style="color:#f92672"&gt;-&lt;/span&gt;d lzldb &lt;span style="color:#75715e"&gt;--table lzlpg -p 6666 -no-kill-backend &amp;gt; pgrepack_lzlpg_log.log 2&amp;gt;&amp;amp;1 &amp;amp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 class="relative group"&gt;长事务问题
 &lt;div id="长事务问题" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%95%bf%e4%ba%8b%e5%8a%a1%e9%97%ae%e9%a2%98" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;长事务的知识点没有多少，及时告警及时处理就行了，但长事务问题绝对值得拿出来单独批斗。&lt;/p&gt;
&lt;p&gt;长事务会导致许多问题，例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;锁不释放导致应用阻塞&lt;/li&gt;
&lt;li&gt;wal不回收导致磁盘告警&lt;/li&gt;
&lt;li&gt;死元组不回收导致sql性能下降&lt;/li&gt;
&lt;li&gt;还有些奇葩性能问题跟长事务相关&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;pg的长事务危害要比oracle、mysql来得大的多，pg中的长事务一定要严格管理。&lt;/p&gt;

&lt;h2 class="relative group"&gt;子事务问题
 &lt;div id="子事务问题" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%ad%90%e4%ba%8b%e5%8a%a1%e9%97%ae%e9%a2%98" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;blockquote&gt;&lt;p&gt;“Subtransactions are basically cursed. Rip em out.”&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;子事务会造成很多问题，也是我们常踩的坑，在行业中也经常遇到子事务导致的问题。&lt;/p&gt;
&lt;p&gt;行业踩坑记录：&lt;/p&gt;
&lt;p&gt;&lt;a href="https://pganalyze.com/blog/5mins-postgres-17-configurable-slru-cache" target="_blank" rel="noreferrer"&gt;Waiting for Postgres 17: Configurable SLRU cache sizes for increased performance&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://knowledge.enterprisedb.com/hc/en-us/articles/13523268146972-Subtransactions-overflow-and-the-performance-cliff" target="_blank" rel="noreferrer"&gt;Subtransactions-overflow-and-the-performance-cliff&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://about.gitlab.com/blog/2021/09/29/why-we-spent-the-last-month-eliminating-postgresql-subtransactions/" target="_blank" rel="noreferrer"&gt;Why we spent the last month eliminating PostgreSQL subtransactions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;子事务的出现：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;PL/pgSQL&lt;/code&gt; functions containing a block with an &lt;strong&gt;exception&lt;/strong&gt; clause&lt;/li&gt;
&lt;li&gt;&lt;code&gt;savepoints&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;JDBC+&lt;a href="https://jdbc.postgresql.org/documentation/use/" target="_blank" rel="noreferrer"&gt;autosave=always&lt;/a&gt; （默认&lt;code&gt;autosave=never&lt;/code&gt; ）&lt;/li&gt;
&lt;li&gt;ODBC&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;注意OGG使用ODBC驱动，ODBC不能关闭子事务。&lt;/p&gt;
&lt;p&gt;GaussDB提供的ODBC可以关闭子事务，参数&lt;a href="https://support.huaweicloud.com/intl/en-us/centralized-devg-v8-gaussdb/gaussdb-42-0098.html" target="_blank" rel="noreferrer"&gt;ForExtensionConnector&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;所以我们可以建议应用使用子事务不超过64个，但很难建议他们不去使用OGG，因为脱O意味着使用依赖OGG 的数据同步工具。&lt;/p&gt;
&lt;p&gt;子事务问题出现的场景和现象：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1(+)个长事务+子事务溢出+高并发业务，性能急剧下降&lt;/li&gt;
&lt;li&gt;子事务溢出(64+)，性能稍微下降&lt;/li&gt;
&lt;li&gt;子事务溢出(64+)+multixact，性能急剧下降&lt;/li&gt;
&lt;li&gt;1(+)个长事务+1(+)个子事务，查询库性能急剧下降&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;pg17的提升：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;SLRU是clog、multixact、subtrans等用来在共享内存中管理事务关系的。相关的源码定义如下：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/* Number of SLRU buffers to use for subtrans */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define NUM_SUBTRANS_BUFFERS	32 &lt;/span&gt;&lt;span style="color:#75715e"&gt;//SLRU页面个数32个，这是共享内存中的
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Each backend advertises up to PGPROC_MAX_CACHED_SUBXIDS TransactionIds
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * for non-aborted subtransactions of its current top transaction. These
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * have to be treated as running XIDs by other backends.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * We also keep track of whether the cache overflowed (ie, the transaction has
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * generated at least one subtransaction that didn&amp;#39;t fit in the cache).
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * If none of the caches have overflowed, we can assume that an XID that&amp;#39;s not
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * listed anywhere in the PGPROC array is not a running transaction. Else we
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * have to look at pg_subtrans.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define PGPROC_MAX_CACHED_SUBXIDS 64	&lt;/span&gt;&lt;span style="color:#75715e"&gt;//超过64个则溢出，each backend
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;pg17对SLRU的提升：
新增GUC参数可以配置SLRU槽的个数，拆分现有的SLRU锁由单个集中控制锁变为多个bank锁&lt;/p&gt;
&lt;p&gt;提升效果：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/d712858437e4.png" alt="image.png" /&gt;
（https://www.pgevents.ca/events/pgconfdev2024/sessions/session/53/slides/27/SLRU%20Performance%20Issues.pdf）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;子事务处理方案：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;开发规范：不要用&lt;code&gt;savepoints&lt;/code&gt;，考虑&lt;code&gt;on conflict&lt;/code&gt;语法处理写入冲突&lt;/li&gt;
&lt;li&gt;开发规范：不要用&lt;code&gt;exception&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;开发规范：确保jdbc&lt;em&gt;没有&lt;/em&gt;显示打开&lt;code&gt;autosave=always&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;添加监控：针对性的监控&lt;code&gt;pg_stat_slru&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;添加监控：针对性的监控&lt;code&gt;SAVEPOINT&lt;/code&gt; and &lt;code&gt;EXCEPTION &lt;/code&gt;&lt;/li&gt;
&lt;li&gt;CDC规范：谨慎使用ODBC，OGG或其他用到ODBC的工具，需要切割事务，一个大事务最高子事务个数上限为5W&lt;/li&gt;
&lt;li&gt;升级版本：升级到PG17&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;并发与性能
 &lt;div id="并发与性能" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%b9%b6%e5%8f%91%e4%b8%8e%e6%80%a7%e8%83%bd" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;快照和并发参数调整
 &lt;div id="快照和并发参数调整" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%bf%ab%e7%85%a7%e5%92%8c%e5%b9%b6%e5%8f%91%e5%8f%82%e6%95%b0%e8%b0%83%e6%95%b4" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;参数名&lt;/th&gt;
 &lt;th&gt;参数类型&lt;/th&gt;
 &lt;th&gt;默认值&lt;/th&gt;
 &lt;th&gt;建议值&lt;/th&gt;
 &lt;th&gt;是否需要重启&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;old_snapshot_threshold&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;cpu&lt;/td&gt;
 &lt;td&gt;-1（社区版）&lt;/td&gt;
 &lt;td&gt;-1&lt;/td&gt;
 &lt;td&gt;是&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;max_parallel_workers_per_gather&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;cpu&lt;/td&gt;
 &lt;td&gt;2&lt;/td&gt;
 &lt;td&gt;0&lt;/td&gt;
 &lt;td&gt;否&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;old_snapshot_threshold&lt;/code&gt;参数打开&lt;em&gt;很容易&lt;/em&gt;引起性能问题，网上资料已经很多了自行搜索，哪怕是需要重启数据库，也强烈推荐关闭参数。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;max_parallel_workers_per_gather&lt;/code&gt; 参数会自动开墙大sql的并行，但是并行为2效率不会成比例提高2倍，参数建议在特殊场景下使用，如跑批时显示指定并行度。由于不需要重启，也就顺手一改的事。&lt;/p&gt;
&lt;p&gt;关闭&lt;code&gt;old_snapshot_threshold&lt;/code&gt;会不会有问题？&lt;/p&gt;
&lt;p&gt;不会。&lt;code&gt;old_snapshot_threshold&lt;/code&gt;参数目的是为了限制长事务，因为pg长事务很容易引起性能问题，但是参数本身也会引发性能问题就得不偿失了。&lt;/p&gt;
&lt;p&gt;处理长事务可以很多手段：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;长事务监控。这是最重要的，而且监控已经比较成熟了。&lt;/li&gt;
&lt;li&gt;设置&lt;code&gt;statement_timeout&lt;/code&gt;，默认0&lt;/li&gt;
&lt;li&gt;设置&lt;code&gt;transaction_timeout&lt;/code&gt; ，默认0，版本17=+支持&lt;/li&gt;
&lt;li&gt;设置&lt;code&gt;lock_timeout&lt;/code&gt; ，默认0，DDL语句建议会话级别开启&lt;/li&gt;
&lt;li&gt;设置&lt;code&gt;idle_in_transaction_session_timeout&lt;/code&gt;，默认0，已开启2h&lt;/li&gt;
&lt;li&gt;设置&lt;code&gt;idle_session_timeout&lt;/code&gt; ，默认0，这个场景没用&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 class="relative group"&gt;高并发提交导致LWLOCK:WALWrite
 &lt;div id="高并发提交导致lwlockwalwrite" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%ab%98%e5%b9%b6%e5%8f%91%e6%8f%90%e4%ba%a4%e5%af%bc%e8%87%b4lwlockwalwrite" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/liuzhilong62/blogs/blob/main/PostgreSQL%E6%A1%88%E4%BE%8B/%E6%A1%88%E4%BE%8B-insert%20value%E5%81%B6%E5%8F%91%E6%85%A2%E5%88%86%E6%9E%90.md" target="_blank" rel="noreferrer"&gt;案例-insert value偶发慢分析&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;记忆点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;IO:WALWrite只有1个，而LWLOCK:WALWrite有几十个&lt;/li&gt;
&lt;li&gt;不能直接看到LWLOCK的blocking chain，但是我可以从源码中得知，LWLOCK:WALWrite在等待IO:WALWrite&lt;/li&gt;
&lt;li&gt;在这种并发高的小事务场景中，提高wal buffer内存大小理论上效果不会太理想&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;会引起什么问题？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;并发写入阻塞，写入接口变慢，活动会话可能上涨&lt;/li&gt;
&lt;li&gt;高并发小事务无法压榨磁盘IO&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;解决办法：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;业务打散并发写入&lt;/li&gt;
&lt;li&gt;业务合并提交&lt;/li&gt;
&lt;li&gt;分析FPI，尝试减少FPI（参考FPI小节）&lt;/li&gt;
&lt;li&gt;组提交（&lt;a href="https://www.postgresql.org/docs/17/runtime-config-wal.html#GUC-COMMIT-DELAY" target="_blank" rel="noreferrer"&gt;待研究&lt;/a&gt;）&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;WAL与延迟
 &lt;div id="wal与延迟" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#wal%e4%b8%8e%e5%bb%b6%e8%bf%9f" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;FPI与checkpoint参数
 &lt;div id="fpi与checkpoint参数" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#fpi%e4%b8%8echeckpoint%e5%8f%82%e6%95%b0" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;pg的wal FPI发生在checkpoint后首次写入相关page时，所以checkpoint越频繁FPI出现的概率越高。&lt;/p&gt;
&lt;p&gt;checkpoint频率与两个参数相关：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;checkpoint_timeout&lt;/li&gt;
&lt;li&gt;max_wal_size&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;原理如下：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/0197be136174.png" alt="image.png" /&gt;
(Egor Rogov PoStgreSQL 14 Internals)&lt;/p&gt;
&lt;p&gt;max_wal_size默认是1GB，这对于负载高的库来说太小了，一般来说可以调大这个参数以减少FPI。&lt;/p&gt;
&lt;p&gt;checkpoint_timeout默认是5分钟，目前来看比较合理。&lt;/p&gt;

&lt;h3 class="relative group"&gt;FPI与离散写
 &lt;div id="fpi与离散写" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#fpi%e4%b8%8e%e7%a6%bb%e6%95%a3%e5%86%99" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;即使调大了checkpoint的间隔，可能还是会有 FPI 问题，此时需要再排查业务是否有 UUID 离散写情况，可能需要业务改造为 sequence 或其他 UUID 方案。&lt;/p&gt;
&lt;p&gt;找到具体索引示例：&lt;/p&gt;
&lt;p&gt;1.查看FPI是否严重&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--stats=record&lt;/code&gt;比较好用&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pg_waldump -z --stats&lt;span style="color:#f92672"&gt;=&lt;/span&gt;record 00000001000001860000001B&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;2.排序哪个rel的FPW比较多&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pg_waldump 00000001000001860000001B|grep FPW|awk -F &lt;span style="color:#e6db74"&gt;&amp;#39;:&amp;#39;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;{print $7}&amp;#39;&lt;/span&gt;|awk &lt;span style="color:#e6db74"&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt;|sort -n|uniq -c |sort -r|head -10&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 class="relative group"&gt;逻辑复制和复制槽
 &lt;div id="逻辑复制和复制槽" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%80%bb%e8%be%91%e5%a4%8d%e5%88%b6%e5%92%8c%e5%a4%8d%e5%88%b6%e6%a7%bd" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;逻辑复制问题非常多，也是社区重点优化项之一，几乎每个版本都有很大提升。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/liuzhilong62/blogs/blob/main/PostgreSQL%E5%86%85%E5%8A%9F%E4%BF%AE%E7%82%BC/PostgreSQL%E9%80%BB%E8%BE%91%E5%A4%8D%E5%88%B6.md" target="_blank" rel="noreferrer"&gt;逻辑复制和复制槽基础知识&lt;/a&gt;&lt;/p&gt;

&lt;h3 class="relative group"&gt;spill问题
 &lt;div id="spill问题" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#spill%e9%97%ae%e9%a2%98" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/liuzhilong62/blogs/blob/main/PostgreSQL%E6%A1%88%E4%BE%8B/PG%E8%B5%B7%E5%BA%93%E9%80%BB%E8%BE%91%E5%92%8Cspill%E5%AF%BC%E8%87%B4%E8%B5%B7%E5%BA%93%E6%85%A2%E9%97%AE%E9%A2%98%E5%88%86%E6%9E%90.md" target="_blank" rel="noreferrer"&gt;PG起库逻辑和spill导致起库慢问题分析&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;spill记忆点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;spill是逻辑解码的时候内存放不下事务信息了所以放到磁盘，spill文件存放的就是事务信息&lt;/li&gt;
&lt;li&gt;每个walsender都有独立的解码，所以每个逻辑复制都有自己的spill&lt;/li&gt;
&lt;li&gt;大事物spill时，会有大spill文件，一般文件数比较少&lt;/li&gt;
&lt;li&gt;子事务spill时，每个子事务对应一个spill文件&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;版本：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PG12及以前是写死的4096条changes&lt;/li&gt;
&lt;li&gt;PG13新增&lt;code&gt;logical_decoding_work_mem&lt;/code&gt;参数，可调整内存大小以减少spill概率&lt;/li&gt;
&lt;li&gt;PG14及以后支持流式复制Streaming&lt;/li&gt;
&lt;li&gt;触发流式复制也需要一定的条件，所以即使有流式复制也可能会发生spill&lt;/li&gt;
&lt;li&gt;PG17新增&lt;code&gt;debug_logical_replication_streaming&lt;/code&gt;参数以强制触发流式传输&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;walsender阻止停库
 &lt;div id="walsender阻止停库" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#walsender%e9%98%bb%e6%ad%a2%e5%81%9c%e5%ba%93" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/liuzhilong62/blogs/blob/main/PostgreSQL%E6%A1%88%E4%BE%8B/PG%E5%81%9C%E5%BA%93%E9%80%BB%E8%BE%91%E5%92%8Cwalsender%E9%98%BB%E6%AD%A2%E5%81%9C%E5%BA%93%E9%97%AE%E9%A2%98%E5%88%86%E6%9E%90.md" target="_blank" rel="noreferrer"&gt;PG停库逻辑和walsender阻止停库问题分析&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;其实任意进程不退出都会阻止停库，问题在于哪些比较容易搞出事。从停库代码流程来看archiver、walsender会常阻止停库，因为他们在停库阶段会做最后一次归档or日志传递。


&lt;img src="https://camo.githubusercontent.com/45e44c384cdf1c41caf9d2018076cf420cd48c9d49be1b2078262b4303be2627/68747470733a2f2f6f73732d656d637370726f642d7075626c69632e6d6f64622e70726f2f696d6167652f656469746f722f32303235303130342d313837353338333238343037393830343431365f343538372e706e67" alt="" /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如果停库卡在walsender，尝试用&lt;code&gt;kill&lt;/code&gt;杀掉walsender而不是直接&lt;code&gt;kill -9&lt;/code&gt; ，此时checkpoint还没有跑完，强制停库会造成不一致停库。注意强制停库也最好用&lt;code&gt;pg_ctl stop -D $PGDATA -m i&lt;/code&gt;来停库，而不是直接&lt;code&gt;kill -9 &lt;/code&gt;&lt;/li&gt;
&lt;li&gt;如果停库卡在archiver，可以直接kill -9，因为checkpoint已经跑完了，库是一致性状态&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;分区表
 &lt;div id="分区表" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%88%86%e5%8c%ba%e8%a1%a8" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/liuzhilong62/blogs/blob/main/PostgreSQL%E5%86%85%E5%8A%9F%E4%BF%AE%E7%82%BC/PostgreSQL%E5%88%86%E5%8C%BA%E8%A1%A8.md" target="_blank" rel="noreferrer"&gt;分区表基础知识&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;由于PG分区表其实是很有特点的，有些特性知识不研究就不知道，开发一般弄不明白pg分区表，所以在使用分区表时会留下很多坑&lt;/p&gt;

&lt;h3 class="relative group"&gt;分区表父表和子表索引不一致
 &lt;div id="分区表父表和子表索引不一致" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%88%86%e5%8c%ba%e8%a1%a8%e7%88%b6%e8%a1%a8%e5%92%8c%e5%ad%90%e8%a1%a8%e7%b4%a2%e5%bc%95%e4%b8%8d%e4%b8%80%e8%87%b4" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;由于创建子分区不规范，很多索引是在子表上建的（实际上不应该单独在子表上建索引），也没有做 ”所有子表创建索引+attach索引“的操作，导致父表其实没有索引或没用有效索引。父表因为没有数据所以其上没索引对业务没有影响，影响的是新建子分区时，只会继承父表索引，导致新的子表可能会缺少索引。&lt;/p&gt;
&lt;p&gt;父表失效索引比较好处理，参考&lt;a href="https://github.com/liuzhilong62/blogs/blob/main/PostgreSQL%E5%86%85%E5%8A%9F%E4%BF%AE%E7%82%BC/PostgreSQL%E5%88%86%E5%8C%BA%E8%A1%A8.md#%E5%88%9B%E5%BB%BA%E5%88%86%E5%8C%BA%E7%B4%A2%E5%BC%95%E7%9A%84%E6%AD%A3%E7%A1%AE%E5%A7%BF%E5%8A%BF" target="_blank" rel="noreferrer"&gt;创建分区索引的正确姿势&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--ONLY方式在分区主表上创建失效索引。快，会阻塞后续dml，会影响业务，需要关注长事务
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;CREATE&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;INDEX&lt;/span&gt; IDX_DATECREATED &lt;span style="color:#66d9ef"&gt;ON&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ONLY&lt;/span&gt; lzlpartition1(date_created);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--CONCURRENTLY在各个分区子表上创建索引。慢，不会阻塞后续dml，不会影响业务，但需要关注DML长事务防止本身失败
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; concurrently idx_datecreated_202302 &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzlpartition1_202302(date_created);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--所有索引attach。快，不会发生业务阻塞
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ALTER&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;INDEX&lt;/span&gt; idx_datecreated ATTACH PARTITION idx_datecreated_202302;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;父表没有主键比较难处理，参考&lt;a href="https://github.com/liuzhilong62/blogs/blob/main/PostgreSQL%E5%86%85%E5%8A%9F%E4%BF%AE%E7%82%BC/PostgreSQL%E5%88%86%E5%8C%BA%E8%A1%A8.md#%E5%88%86%E5%8C%BA%E8%A1%A8%E6%B7%BB%E5%8A%A0%E4%B8%BB%E9%94%AE%E5%92%8C%E5%94%AF%E4%B8%80%E7%B4%A2%E5%BC%95" target="_blank" rel="noreferrer"&gt;分区表添加主键和唯一索引&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;添加主键在主表上申请&lt;code&gt;AccessExclusiveLock&lt;/code&gt;，阻塞一切。 分区表上添加索引很慢，主键又会造成后续的阻塞，目前没有影响较小的在分区表上添加主键的办法。虽然没有达到目的，可以考虑用“attach唯一索引+非空约束”的办法；或者只能申请较长的停分区表业务，等待创建索引完成；或者通过第三方同步工具将数据插入一个带主键的分区表。&lt;/p&gt;

&lt;h3 class="relative group"&gt;滥用default分区
 &lt;div id="滥用default分区" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%bb%a5%e7%94%a8default%e5%88%86%e5%8c%ba" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/liuzhilong62/blogs/blob/main/PostgreSQL%E6%A1%88%E4%BE%8B/%E6%B2%A1%E6%9C%89%E9%98%BB%E5%A1%9E%E4%B8%BA%E4%BB%80%E4%B9%88partition%20of%E5%88%9B%E5%BB%BA%E5%AD%90%E5%88%86%E5%8C%BA%E5%BE%88%E6%85%A2%EF%BC%9F.md" target="_blank" rel="noreferrer"&gt;default分区过大导致parition of创建子分区长期阻塞&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;原因很简单：分区表新增子分区时，由于建分区的语句需要校验default分区中的数据，保证新分区数据范围与default分区的现有数据不冲突，导致&lt;code&gt;create table partition of&lt;/code&gt;读取了大量的default分区数据，新建分区一直未完成。随后阻塞扩大，业务数据无法查询和写入。&lt;/p&gt;
&lt;p&gt;default分区滥用是普遍的问题！社区pg本来也没有提供interval分区功能，开发哪天忘记创建分区了，数据就跑到default分区，也不会有任何报错和告警。但是日复一日···default分区就越来越大，最后发版建分区搞出问题。&lt;/p&gt;
&lt;p&gt;default分区过大不能一直这么放着，虽然attach建分区可以避开阻塞问题，但出于各种角度考虑还是需要排这个雷。&lt;/p&gt;
&lt;p&gt;default分区数据处理方案1：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;detach default子分区，然后合理创建子分区，再将default表数据回插到分区表中。&lt;/li&gt;
&lt;li&gt;如有必要，可在detach且创建合理子分区后，创建一个空的default分区，以保持业务数据的连续性。&lt;/li&gt;
&lt;li&gt;注意detach跟attach不同，detach需要主表的8级锁。PG14支持detach concurrently，但不能有default分区。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;default分区数据处理方案2：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;detach default子分区，然后合理创建子分区，detached后的default表attach成普通子分区，需要注意range的范围。&lt;/li&gt;
&lt;li&gt;如有必要，可在detach且创建合理子分区后，创建一个空的default分区，以保持业务数据的连续性。&lt;/li&gt;
&lt;li&gt;注意detach跟attach不同，detach需要主表的8级锁。PG14支持detach concurrently，但不能有default分区。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;default分区数据处理方案3：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;新建表所有数据通过dts同步&lt;/li&gt;
&lt;li&gt;rename表&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;方案3看起来是最矬的，但是我个人最推荐。原因是如果你的手里有5套库需要处理，那么可以用精湛方案没问题，如果你的手里有200套库需要处理，那么要投入的人力成本，dts应该是最佳落地方案。&lt;/p&gt;

&lt;h3 class="relative group"&gt;分区表select权限丢失导致执行计划异常
 &lt;div id="分区表select权限丢失导致执行计划异常" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%88%86%e5%8c%ba%e8%a1%a8select%e6%9d%83%e9%99%90%e4%b8%a2%e5%a4%b1%e5%af%bc%e8%87%b4%e6%89%a7%e8%a1%8c%e8%ae%a1%e5%88%92%e5%bc%82%e5%b8%b8" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;用户对分区子表没用select权限，会导致用户执行的sql不能访问子表的统计信息，从而导致执行计划异常。正常partition of创建的分区表是不带select权限的，从主表访问数据可以访问到，所以这是范围比较大的问题。&lt;/p&gt;
&lt;p&gt;解决方案&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;让云平台解决，自动化处理&lt;/li&gt;
&lt;li&gt;落地select子分区权限的开发规范&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;高并发分区全扫描和LWLock:lockmanager
 &lt;div id="高并发分区全扫描和lwlocklockmanager" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%ab%98%e5%b9%b6%e5%8f%91%e5%88%86%e5%8c%ba%e5%85%a8%e6%89%ab%e6%8f%8f%e5%92%8clwlocklockmanager" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;这也是一个很常见的问题！&lt;/p&gt;
&lt;p&gt;推荐看下aws的文档，写的很清楚了：&lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/wait-event.lw-lock-manager.html" target="_blank" rel="noreferrer"&gt;https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/wait-event.lw-lock-manager.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;问题现象：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;活动会话暴涨&lt;/li&gt;
&lt;li&gt;LWLock:lockmanager等待事件严重&lt;/li&gt;
&lt;li&gt;数据库性能cliff&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;发生场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;sql查询多个分区&lt;/li&gt;
&lt;li&gt;该sql并发较高&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;记忆点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;fastpath锁机制本身是为了“弱锁”快速访问，提升数据库并发而设计的&lt;/li&gt;
&lt;li&gt;fastpath锁等级小于等于3。即是select、select for xxx、DML才能使用（弱锁便是锁模式必须小于&lt;code&gt;ShareUpdateExclusiveLock&lt;/code&gt;，也就是1、2、3级锁有机会使用到fastpath）。换句话说就是为了正常业务都受益&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FP_LOCK_SLOTS_PER_BACKEND&lt;/code&gt;，本地进程持有fastpath的锁不超过16个，超过16就要到内存中去获得锁，&lt;code&gt;LWLock:lockmanager&lt;/code&gt;在此时产生&lt;/li&gt;
&lt;li&gt;不仅是表，每个被访问的索引都要加锁&lt;/li&gt;
&lt;li&gt;这个问题跟分区数量没有多大关系，即便分区比较少也可能触发&lt;code&gt;LWLock:lockmanager&lt;/code&gt;等待导致性能下降&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;可以计算一下，如果一个分区表上有1个主键和2个普通索引，多少个分区就会用不到fastpath？&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;（&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;个索引&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;表本身）&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;父表本身&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;个子分区&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;是的，3个子分区的全分区扫描就会可能会出现这个LWLock:lockmanager等待了。&lt;/p&gt;
&lt;p&gt;如果是普通表的话，表上建16个索引也会用不到fastpath。&lt;/p&gt;
&lt;p&gt;解决办法：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对于表不是特别大的，合并分区成普通表&lt;/li&gt;
&lt;li&gt;sql加入分区过滤条件&lt;/li&gt;
&lt;li&gt;减少索引（比较没用，因为一般子分区数就超过16个了）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;难点：&lt;/p&gt;
&lt;p&gt;在oracle脱O到PG库的场景中，由于oracle支持全局索引，主键和唯一索引可以不带分区键，到pg后主键和唯一索引必须要带分区键。&lt;/p&gt;
&lt;p&gt;主键示例如下：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;idxlzl(primarykey) &lt;span style="color:#75715e"&gt;--oracle
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;idxlzl(primarykey,partitionkey) &lt;span style="color:#75715e"&gt;--pg&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;常见的表上的sql是这样：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; col &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; tlzl &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; primarykey&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;12345&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这个场景要推动业务在这个sql上添加分区条件吗？很难。阻力在于“我已经传入主键了，你还要我怎样？如果我什么数据都知道，我还要查数据库吗？”&lt;/p&gt;
&lt;p&gt;如果是这样，只能推荐改造分区表为普通表，目前没有想出其他好办法。&lt;/p&gt;

&lt;h2 class="relative group"&gt;内存
 &lt;div id="内存" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%86%85%e5%ad%98" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;对象过多导致relcache过大
 &lt;div id="对象过多导致relcache过大" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%af%b9%e8%b1%a1%e8%bf%87%e5%a4%9a%e5%af%bc%e8%87%b4relcache%e8%bf%87%e5%a4%a7" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;记忆点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;relcache保留relation相关的元数据：oid、pg_class、分区表、子事务、行安全策略、统计信息、索引元数据、am等等。&lt;/li&gt;
&lt;li&gt;每个会话都有自己的(rel)cache缓存系统数据（元数据等）&lt;/li&gt;
&lt;li&gt;一般这个cache很小。当catalog很大且会话访问过所有catalog时，cache会变的很大&lt;/li&gt;
&lt;li&gt;cache的管理很简单，&lt;strong&gt;没有删除机制和limit限制&lt;/strong&gt;（其实有invalidation消息）&lt;/li&gt;
&lt;li&gt;关闭会话会释放cache&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;解决办法：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;减少对象，特别是要检查分区表子分区数是否太多了&lt;/li&gt;
&lt;li&gt;设置激进的连接池断连参数，让业务连接中断更频繁&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;内存碎片问题
 &lt;div id="内存碎片问题" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%86%85%e5%ad%98%e7%a2%8e%e7%89%87%e9%97%ae%e9%a2%98" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;命令推荐：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cat /proc/meminfo|grep whatyouneed
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cat /proc/buddyinfo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## cg内存&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/opt/cgtools/cginfo -t perf -s mem 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#重点关注 pgscand/s直接内存回收指标，一般几万就代表有问题&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sar -B -s &lt;span style="color:#e6db74"&gt;&amp;#34;08:00:00&amp;#34;&lt;/span&gt; -e &lt;span style="color:#e6db74"&gt;&amp;#34;09:00:00&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#min_free_kbytes设置:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cat /proc/sys/vm/min_free_kbytes
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#所有进程的物理总内存使用量：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;grep Pss /proc/&lt;span style="color:#f92672"&gt;[&lt;/span&gt;1-9&lt;span style="color:#f92672"&gt;]&lt;/span&gt;*/smaps | awk &lt;span style="color:#e6db74"&gt;&amp;#39;{total+=$2}; END {printf &amp;#34;%d kB\n&amp;#34;, total }&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#某进程PSS内存：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cat /proc/90875/smaps |grep Pss |awk &lt;span style="color:#e6db74"&gt;&amp;#39;{sum+=$2 };END {print sum/1024}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#某进程的RSS内存 ：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cat /proc/68729/smaps |grep Rss |awk &lt;span style="color:#e6db74"&gt;&amp;#39;{sum+=$2 };END {print sum/1024}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#某进程私有内存：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cat /proc/90875/smaps|sed &lt;span style="color:#e6db74"&gt;&amp;#39;/zero/,/VmFlags/d&amp;#39;&lt;/span&gt; |grep Private |awk &lt;span style="color:#e6db74"&gt;&amp;#39;{sum+=$2 };END {print sum/1024}&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;min_free_kbytes：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://camo.githubusercontent.com/ec10b5b4434febdb6675545e2beaa60646be264db9fb8259cd787cdd4771054b/68747470733a2f2f692d626c6f672e6373646e696d672e636e2f626c6f675f6d6967726174652f35653435303466323634303231633438386438613637623962333665666265322e706e67" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;（&lt;a href="https://vivani.net/2022/06/14/linux-kernel-tuning-page-allocation-failure/" target="_blank" rel="noreferrer"&gt;https://vivani.net/2022/06/14/linux-kernel-tuning-page-allocation-failure/&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;当可用内存较低时kswapd守护进程会被唤醒以释放页&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pages_low:当可用的空闲页面数量低于pages_low 时，buddy allocator会唤醒 kswapd 进程，内核开始将页换出到硬盘。&lt;/li&gt;
&lt;li&gt;pages_min:当可用页面数量达到 pages_min时，说明页回收工作的压力就比较大，因为内存域中急需空闲页。分配器将以同步的方式执行 kswapd 工作，有时也称为直接回收。&lt;/li&gt;
&lt;li&gt;pages_high:一旦 kswapd 被唤醒开始释放页面，只有在可用页面数量达到pages_high时，内核才认为该区域是“平衡的”。如果水位线达到pages_high，kswapd 将重新进入休眠状态。空闲页多于pages_high，则内核认为zone的状态是理想的。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;vm.min_free_kbytes&lt;/code&gt;也就是min_pages线，十分重要的操作系统参数。非常低的值会阻止系统有效地回收内存，这可能会导致系统崩溃并中断服务。太高的值会增加系统回收活动，造成分配延迟，这可能导致系统立即进入内存不足状态。&lt;/p&gt;
&lt;p&gt;优化效果：&lt;/p&gt;
&lt;p&gt;min_free_kbytes调大+部署非业务时段drop cache，问题已经少很多了。&lt;/p&gt;
&lt;p&gt;为什么是调高min_free_kbytes？&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;This is used to force the Linux VM to keep a minimum number of kilobytes free. The VM uses this number to compute a watermark[WMARK_MIN] value for each lowmem zone in the system. Each lowmem zone gets a number of reserved free pages based &lt;strong&gt;proportionally&lt;/strong&gt; on its size.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href="https://www.kernel.org/doc/html/latest/admin-guide/sysctl/vm.html#min-free-kbytes" target="_blank" rel="noreferrer"&gt;min_free_kbytes&lt;/a&gt;调高的本质不是为了把对应的min page线提高已更高概率地触发直接内存回收，而是因为low page线在linux7以前是无法调整的，只能通过调高min page线以等比例的提高low page线以更容易触发异步回收，并给直接内存回收的触发创造缓冲时间。&lt;/p&gt;
&lt;p&gt;Redhat 8 版本增加了2个内存参数来优化内存回收 ：watermark_scale_factor 可以在不调整min_free_kbytes情况下，抬高水位线。&lt;/p&gt;
&lt;p&gt;建议开启大页：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;大页在业务（pg库）申请连续内存的时候性能较好&lt;/li&gt;
&lt;li&gt;大页也有助于减少page cache大小&lt;/li&gt;
&lt;li&gt;shared_buffer可使用大页，需开启Huge_pages和操作系统已开启大页&lt;/li&gt;
&lt;li&gt;生产开启了大页的库，性能有提升，问题更少&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.Managing.html#AuroraPostgreSQL.Managing.HugePages" target="_blank" rel="noreferrer"&gt;aws大页标准&lt;/a&gt;：除了几个测试套餐外，其他均默认开启大页且不可关闭&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;Huge_pages&lt;/code&gt; parameter is turned on by default for all DB instance classes other than t3.medium,db.t3.large,db.t4g.medium,db.t4g.large instance classes. You can&amp;rsquo;t change the &lt;code&gt;huge_pages&lt;/code&gt; parameter value or turn off this feature in the supported instance classes of Aurora PostgreSQL.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 class="relative group"&gt;cgroup和主机内存错位
 &lt;div id="cgroup和主机内存错位" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#cgroup%e5%92%8c%e4%b8%bb%e6%9c%ba%e5%86%85%e5%ad%98%e9%94%99%e4%bd%8d" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;cgroup中的内存达到cg内存限制后，kswapd 进程会优先回收cg中的内存，云主机售卖资源和cgroup配置，可能存在主机空闲内存在水位之上，而cg内存紧张，主机层面的pages_low ，导致kswapd 不会异步回收主机内存也不会回收cg内存，最终是通过触发直接回收内存CG中的DB内存需求。&lt;/p&gt;
&lt;p&gt;​	根因在于cgroup中没有单独的free page内存管理机制。&lt;/p&gt;
&lt;p&gt;​ 这种情况只能把cg内存调高，云主机内存更多的超卖，以达更容易达到主机的pages_low。&lt;/p&gt;

&lt;h3 class="relative group"&gt;shared_buffer和pagecache
 &lt;div id="shared_buffer和pagecache" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#shared_buffer%e5%92%8cpagecache" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;pg是double buffer机制，目前还没有direct IO。&lt;/p&gt;
&lt;p&gt;double buffer是指DB shared buffer一层共享内存，OS pagecache一层共享内存。在真实场景中，pagecache一般远大于shared buffer，而pagecache又是算在cgroup mem中的，没有算到监控cg内存中···&lt;/p&gt;
&lt;p&gt;总之，要留足内存给pagecache使用，shared buffer不要超过太大（目前来看20GB足够），除非可以明显观察到等待事件中有buffer mapping相关内存等待，不然不要去调太大。&lt;/p&gt;

&lt;h3 class="relative group"&gt;work_mem无法限制hash join/hash aggregate使用的内存
 &lt;div id="work_mem无法限制hash-joinhash-aggregate使用的内存" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#work_mem%e6%97%a0%e6%b3%95%e9%99%90%e5%88%b6hash-joinhash-aggregate%e4%bd%bf%e7%94%a8%e7%9a%84%e5%86%85%e5%ad%98" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;hash_mem_multiplier&lt;/strong&gt; 用于限制基于hash-based operations的内存大小（应该包括hash join，hash agg等），限制是&lt;code&gt;hash_mem_multiplier&lt;/code&gt;*&lt;code&gt;work mem&lt;/code&gt;。&lt;code&gt;hash_mem_multiplier&lt;/code&gt;默认为2。&lt;/p&gt;
&lt;p&gt;在pg13以前虽然可以限制&lt;code&gt;work mem&lt;/code&gt;，但是无法限制1个query使用了多少个hash操作，所以pg13增加了这个参数。也就是说13以前，是很难限制hash table的内存的。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;在pg12-的生产环境中找到消耗300G内存的一个会话，罪魁祸首就是低版本没有hash table限制和执行计划错误的使用hash table&lt;/em&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;其他问题
 &lt;div id="其他问题" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%85%b6%e4%bb%96%e9%97%ae%e9%a2%98" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;排他备份和起库问题
 &lt;div id="排他备份和起库问题" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%8e%92%e4%bb%96%e5%a4%87%e4%bb%bd%e5%92%8c%e8%b5%b7%e5%ba%93%e9%97%ae%e9%a2%98" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;正常来说，数据库停库再起库，起库的位置从pg_controldata中的LSN位置获取，但是如果PGDATA目录下有一个&lt;code&gt;backup_label&lt;/code&gt;文件，启动位置LSN会从&lt;code&gt;backup_label&lt;/code&gt;文件获取。&lt;/p&gt;
&lt;p&gt;会引起什么问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;磁盘快照直接打的是data目录快照，label文件有可能在里面，如果库大备份时间长的话，起库时间就很长&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;大问题：某些原因生产停库后，库启动会很久。根因在于起库的LSN应该从controldata中获取，而不是备份中&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;版本变化：&lt;/p&gt;
&lt;p&gt;pg13:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pg_start_backup()&lt;/code&gt;
&lt;code&gt;pg_stop_backup()&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;支持排他和非排他模式，默认就是排他模式。排他模式会在start的时候在data目录下创建&lt;code&gt;backup_label&lt;/code&gt;文件，stop的时候会清理。非排他模式start的时候不会创建label文件，stop的时候返回label信息。&lt;/p&gt;
&lt;p&gt;pg15:
&lt;code&gt;pg_backup_start()&lt;/code&gt;
&lt;code&gt;pg_backup_stop()&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;函数名称变化，&lt;strong&gt;移除了排他备份模式&lt;/strong&gt;。不会在启动备份的时候写&lt;code&gt;backup_label&lt;/code&gt;文件，而是在结束备份的时候写入到备份区域。&lt;/p&gt;

&lt;h3 class="relative group"&gt;pg_stat_activty无法查询
 &lt;div id="pg_stat_activty无法查询" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#pg_stat_activty%e6%97%a0%e6%b3%95%e6%9f%a5%e8%af%a2" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;现象：&lt;/p&gt;
&lt;p&gt;pg_stat_activty无法查询&lt;/p&gt;
&lt;p&gt;当时的pstack如下：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; pgstat_read_current_status () &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; pgstat.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;3642&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x0000000000727181 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; pgstat_read_current_status () &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; pgstat.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;2788&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; pgstat_fetch_stat_numbackends () &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; pgstat.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;2789&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x000000000083f2ee &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; pg_stat_get_activity (fcinfo&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x25c2d98) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; pgstatfuncs.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;575&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x000000000065058f &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; ExecMakeTableFunctionResult (setexpr&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x25b1d28, econtext&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x25b1c48, argContext&lt;span style="color:#f92672"&gt;=&amp;lt;&lt;/span&gt;optimized &lt;span style="color:#66d9ef"&gt;out&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;, expectedDesc&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x2545218, randomAccess&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; execSRF.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;234&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x00000000006609dc &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; FunctionNext (node&lt;span style="color:#f92672"&gt;=&lt;/span&gt;node&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x25b1b38) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; nodeFunctionscan.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;94&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x000000000065110c &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; ExecScanFetch (recheckMtd&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x660700 &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;FunctionRecheck&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;, accessMtd&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x660720 &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;FunctionNext&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;, node&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x25b1b38) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; execScan.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;133&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;分析：&lt;/p&gt;
&lt;p&gt;代码定位比较明确，卡在&lt;code&gt;st_changecount&lt;/code&gt;成为奇数进入死循环。&lt;/p&gt;
&lt;p&gt;什么场景会触发？OOM（可复现），backend异常退出（可能），terminate（maybe）；这三个场景不代表一定会造成这个问题。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.postgresql.org/message-id/5979.1557543440%40sss.pgh.pa.us" target="_blank" rel="noreferrer"&gt;社区邮件&lt;/a&gt;没有讨论出结果，目前来看触发概率不高。&lt;/p&gt;
&lt;p&gt;解决方案：重启数据库&lt;/p&gt;

&lt;h2 class="relative group"&gt;连接问题和连接池问题
 &lt;div id="连接问题和连接池问题" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%bf%9e%e6%8e%a5%e9%97%ae%e9%a2%98%e5%92%8c%e8%bf%9e%e6%8e%a5%e6%b1%a0%e9%97%ae%e9%a2%98" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;IO error报错
 &lt;div id="io-error报错" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#io-error%e6%8a%a5%e9%94%99" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;IO error报错一般是业务层与数据库连接断开，业务层仍在使用已断连的连接导致的报错。
该问题出现比较频繁，而且由于整个链路上涉及的组件多、知识域宽，所以诊断起来比较困难，以下做一个简单总结。&lt;/p&gt;
&lt;p&gt;已知的主动断连场景：&lt;/p&gt;
&lt;p&gt;1.hikari &lt;code&gt;maxLifetime&lt;/code&gt;
现象：会话保持时间与参数一致。 可能报错原因：业务显示事务执行 select 未提交，连接池断开会话，业务报&lt;code&gt; io error；could not rollback&lt;/code&gt; 相关错误。&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pg.datasouce.maxLifetime&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;2.druid timeout
现象：业务 sql 执行超 20s 后连接断开&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;spring.datasource.dynamic.druid.socketTimeout=20000 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;spring.datasource.dynamic.druid.connectTimeout=20000 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;改为
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;spring.datasource.socketTimeout=3600000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;spring.datasource.connectTimeout=3600000 &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 class="relative group"&gt;业务容器扩容和数据库连接上限
 &lt;div id="业务容器扩容和数据库连接上限" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%b8%9a%e5%8a%a1%e5%ae%b9%e5%99%a8%e6%89%a9%e5%ae%b9%e5%92%8c%e6%95%b0%e6%8d%ae%e5%ba%93%e8%bf%9e%e6%8e%a5%e4%b8%8a%e9%99%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;业务横向扩容和pg库的连接瓶颈：&lt;/p&gt;
&lt;p&gt;HikariCP目前已是SpringBoot默认的连接池，伴随着SpringBoot和微服务的普及，HikariCP 的使用也越来越多。业务每扩容一个pod，数据库连接数都会上涨。原因在于&lt;code&gt;maximumPoolSize&lt;/code&gt;虽然每个pod中配置没有动，但业务节点横向扩展了。从已有节点数、增加节点数、现有数据库连接总数可以成比例的计算出来数据库的空闲连接会加多少。&lt;/p&gt;
&lt;p&gt;应用可以无状态的横向扩容，但是数据库不是，pg的连接上限参数&lt;code&gt;max_connections&lt;/code&gt;，应用成倍的扩容是有可能造成idle连接数就打满了。&lt;code&gt;max_connections&lt;/code&gt;的调整是个很麻烦的工作因为要重启数据库生效。&lt;/p&gt;
&lt;p&gt;pg库连接上限:&lt;/p&gt;
&lt;p&gt;还有一个点在于，业务无限横向扩容，&lt;code&gt;max_connections&lt;/code&gt;应该随云实例套餐调整而调整，但是可以无限往上调整吗？很明显不是的。pg库，无论什么库，idle连接越多性能都会下降。&lt;/p&gt;
&lt;p&gt;可参考&lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.Managing.html#AuroraPostgreSQL.Managing.MaxConnections" target="_blank" rel="noreferrer"&gt;AWS的做法&lt;/a&gt;：
&lt;code&gt;max_connections&lt;/code&gt;与套餐相关，最大值&lt;code&gt;5000 ,LEAST({DBInstanceClassMemory/9531392},5000)&lt;/code&gt;.这可以减少人力运维连接数，也给出了比较合理的最大值&lt;/p&gt;</content:encoded></item><item><title>PG起库逻辑和spill导致起库慢问题分析</title><link>https://lastdba.com/2025/01/04/pg%E8%B5%B7%E5%BA%93%E9%80%BB%E8%BE%91%E5%92%8Cspill%E5%AF%BC%E8%87%B4%E8%B5%B7%E5%BA%93%E6%85%A2%E9%97%AE%E9%A2%98%E5%88%86%E6%9E%90/</link><pubDate>Sat, 04 Jan 2025 00:00:00 +0000</pubDate><guid>https://lastdba.com/2025/01/04/pg%E8%B5%B7%E5%BA%93%E9%80%BB%E8%BE%91%E5%92%8Cspill%E5%AF%BC%E8%87%B4%E8%B5%B7%E5%BA%93%E6%85%A2%E9%97%AE%E9%A2%98%E5%88%86%E6%9E%90/</guid><description>&lt;h2 class="relative group"&gt;问题现象-起库缓慢
 &lt;div id="问题现象-起库缓慢" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e7%8e%b0%e8%b1%a1-%e8%b5%b7%e5%ba%93%e7%bc%93%e6%85%a2" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;版本pg13.2&lt;/p&gt;
&lt;p&gt;数据库启动缓慢，startup进程在读取spill文件，文件名在变化。查看spill文件也很慢，ls -l最后跑出来有800w个文件spill文件。&lt;/p&gt;</description><content:encoded>
&lt;h2 class="relative group"&gt;问题现象-起库缓慢
 &lt;div id="问题现象-起库缓慢" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e7%8e%b0%e8%b1%a1-%e8%b5%b7%e5%ba%93%e7%bc%93%e6%85%a2" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;版本pg13.2&lt;/p&gt;
&lt;p&gt;数据库启动缓慢，startup进程在读取spill文件，文件名在变化。查看spill文件也很慢，ls -l最后跑出来有800w个文件spill文件。&lt;/p&gt;

&lt;h2 class="relative group"&gt;为什么有上千万个spill文件
 &lt;div id="为什么有上千万个spill文件" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e6%9c%89%e4%b8%8a%e5%8d%83%e4%b8%87%e4%b8%aaspill%e6%96%87%e4%bb%b6" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;wal段和LSN的含义
 &lt;div id="wal段和lsn的含义" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#wal%e6%ae%b5%e5%92%8clsn%e7%9a%84%e5%90%ab%e4%b9%89" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;

&lt;h4 class="relative group"&gt;LSN
 &lt;div id="lsn" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#lsn" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;LSN总体是一个64位的bigint，LSN实际长这样&lt;code&gt;42D3B/1732C540&lt;/code&gt;（hex），斜杠&lt;code&gt;/&lt;/code&gt;前是32位逻辑日志号，&lt;code&gt;/&lt;/code&gt;后32位是段号+块号+块内偏移。这4个部分分别是：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;32位&lt;/th&gt;
 &lt;th&gt;8位&lt;/th&gt;
 &lt;th&gt;11位&lt;/th&gt;
 &lt;th&gt;13位&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;逻辑日志号&lt;/td&gt;
 &lt;td&gt;日志段号&lt;/td&gt;
 &lt;td&gt;块号&lt;/td&gt;
 &lt;td&gt;块内偏移&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;块内偏移 8192=2^13&lt;/p&gt;
&lt;p&gt;块号=16M（默认wal段大小）/8192&lt;/p&gt;

&lt;h4 class="relative group"&gt;wal segment
 &lt;div id="wal-segment" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#wal-segment" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;wal文件名由3组16进制数字组成。&lt;/p&gt;
&lt;p&gt;以8k的wal文件&lt;code&gt;0000000300042D3B00000002&lt;/code&gt;为例：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;32位&lt;/th&gt;
 &lt;th&gt;32位&lt;/th&gt;
 &lt;th&gt;32位&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;timeline&lt;/td&gt;
 &lt;td&gt;逻辑日志号&lt;/td&gt;
 &lt;td&gt;日志段号&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;00000003&lt;/td&gt;
 &lt;td&gt;00042D3B&lt;/td&gt;
 &lt;td&gt;00000002&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;可以看出LSN可以定位到wal文件名及文件中offset位置。&lt;/p&gt;
&lt;p&gt;其中，LSN斜杠&lt;code&gt;/&lt;/code&gt;前是逻辑日志号，斜杠&lt;code&gt;/&lt;/code&gt;后8位的日志段号下面都会用到。&lt;/p&gt;

&lt;h3 class="relative group"&gt;spill文件名转换
 &lt;div id="spill文件名转换" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#spill%e6%96%87%e4%bb%b6%e5%90%8d%e8%bd%ac%e6%8d%a2" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;复制槽名：logical_ex2209_rep&lt;/p&gt;
&lt;p&gt;spill文件名：xid-407989064-lsn-42D1E-20000000.spill&lt;/p&gt;
&lt;p&gt;42D1E不是一个完整的LSN，不能直接用&lt;code&gt;pg_walfile_name&lt;/code&gt;来定位wal文件名。42D1E是一个逻辑日志号，如果直接过滤文件名含42D1E的wal文件，可以找到16个wal文件。&lt;/p&gt;
&lt;p&gt;能否通过数字20000000定位到wal日志段号从而定位到哪一个文件呢？&lt;/p&gt;
&lt;p&gt;spill文件名：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Given a replication slot, transaction ID and segment number, fill in the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * corresponding spill file into &amp;#39;path&amp;#39;, which is a caller-owned buffer of size
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * at least MAXPGPATH.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;ReorderBufferSerializedPath&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;char&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;path, ReplicationSlot &lt;span style="color:#f92672"&gt;*&lt;/span&gt;slot, TransactionId xid,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; XLogSegNo segno)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; XLogRecPtr recptr;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;XLogSegNoOffsetToRecPtr&lt;/span&gt;(segno, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, wal_segment_size, recptr);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;snprintf&lt;/span&gt;(path, MAXPGPATH, &lt;span style="color:#e6db74"&gt;&amp;#34;pg_replslot/%s/xid-%u-lsn-%X-%X.spill&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;NameStr&lt;/span&gt;(MyReplicationSlot&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;data.name),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; xid,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (uint32) (recptr &lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;), (uint32) recptr);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;pg_replslot/%s和xid-%u-lsn比较好理解，就是复制槽名称和xid。后面的&lt;code&gt;recptr&lt;/code&gt;还要再看下定义：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Pointer to a location in the XLOG. These pointers are 64 bits wide,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * because we don&amp;#39;t want them ever to overflow.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;typedef&lt;/span&gt; uint64 XLogRecPtr;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;XLogSegNoOffsetToRecPtr&lt;/code&gt;是通过wal日志段号、段大小、offset计算LSN:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define XLogSegNoOffsetToRecPtr(segno, offset, wal_segsz_bytes, dest) \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; (dest) = (segno) * (wal_segsz_bytes) + (offset)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;XLogRecPtr就是LSN！那么&lt;/p&gt;
&lt;p&gt;&lt;code&gt;(uint32) (recptr &amp;gt;&amp;gt; 32)&lt;/code&gt;表示取LSN前32位，&lt;code&gt;(uint32) recptr)&lt;/code&gt;取LSN后32位。&lt;/p&gt;
&lt;p&gt;LSN前32位也就是刚才看到的LSN前半段，lsn-42D1E；LSN后32位实际上信息多了，这里只要LSN后32位中的前几位的段号即可。&lt;/p&gt;
&lt;p&gt;因为传入的offset=0，也传入了segno，那么根本不需要wal日志段内偏移量信息，就可以计算出dest的值。wal_segsz_bytes的真实值是128M*1014*1024，将&lt;code&gt;XLogSegNoOffsetToRecPtr&lt;/code&gt;中的式子转化下为：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;segno&lt;span style="color:#f92672"&gt;=&lt;/span&gt; dest&lt;span style="color:#f92672"&gt;/&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;128&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1024&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1024&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- 再把16进制20000000转化下
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;segno&lt;span style="color:#f92672"&gt;=&lt;/span&gt; x&lt;span style="color:#e6db74"&gt;&amp;#39;20000000&amp;#39;&lt;/span&gt;::int&lt;span style="color:#f92672"&gt;/&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;128&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1024&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1024&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;segno&lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;可以从式子算出日志段号segno，也就可以定位到wal文件号了。&lt;/p&gt;
&lt;p&gt;所以，这里的spill文件名：xid-407989064-lsn-42D1E-20000000.spill对应的wal文件为&lt;/p&gt;
&lt;p&gt;逻辑日志号=42D1E，段号=04：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ls 42D1E*04
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;0000000200042D1E00000004&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;pg_waldump可以看到xid 407989064在里面。&lt;/p&gt;
&lt;p&gt;实际上wal大小在实例创建后也是固定的，即(128*1024*1024)是一个常量，那么segno跟(uint32) recptr绝对相关，但不相等。也就是说切换一个wal日志就会切换一个spill。&lt;/p&gt;
&lt;p&gt;最后总结&lt;strong&gt;spill文件生成规则&lt;/strong&gt;如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;同一个事务id，如果跨wal就会产生多个spill。如：一个不含子事务的大事务跨越3个wal，就会对应3个spill文件&lt;/li&gt;
&lt;li&gt;不同的事务id对应不同的spill。如：1000w个子事务对应1000w个spill&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;spill文件名结构xid-407989064-lsn-42D1E-20000000.spill：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;xid&lt;/th&gt;
 &lt;th&gt;lsn前32位；即wal逻辑日志号&lt;/th&gt;
 &lt;th&gt;由wal日志段号换算；不等于段号&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;xid-407989064&lt;/td&gt;
 &lt;td&gt;lsn-42D1E&lt;/td&gt;
 &lt;td&gt;20000000&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## 恢复出的环境&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;postgres&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ ll |head -100
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;total &lt;span style="color:#ae81ff"&gt;40000276&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;184&lt;/span&gt; Dec &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; 15:20 state
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;196&lt;/span&gt; Dec &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; 13:25 xid-407989064-lsn-42D1E-0.spill
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;208&lt;/span&gt; Dec &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; 13:25 xid-407989064-lsn-42D1E-20000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;540&lt;/span&gt; Dec &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; 16:44 xid-407989064-lsn-42D2A-D0000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;152&lt;/span&gt; Dec &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; 13:09 xid-407989065-lsn-42D1D-C8000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;152&lt;/span&gt; Dec &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; 13:09 xid-407989066-lsn-42D1D-C8000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;152&lt;/span&gt; Dec &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; 13:09 xid-407989068-lsn-42D1D-C8000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;152&lt;/span&gt; Dec &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; 13:09 xid-407989070-lsn-42D1D-C8000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;152&lt;/span&gt; Dec &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; 13:09 xid-407989072-lsn-42D1D-C8000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;152&lt;/span&gt; Dec &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; 13:09 xid-407989076-lsn-42D1D-C8000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;152&lt;/span&gt; Dec &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; 13:09 xid-407989079-lsn-42D1D-C8000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;152&lt;/span&gt; Dec &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; 13:09 xid-407989080-lsn-42D1D-C8000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;152&lt;/span&gt; Dec &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; 13:09 xid-407989082-lsn-42D1D-C8000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;postgres@lzlhost /myhost/liuzhilong/pg_replslot/logical_ex9e15_rep&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ ll |awk &lt;span style="color:#e6db74"&gt;&amp;#39;{print $9}&amp;#39;&lt;/span&gt;|awk -F &lt;span style="color:#e6db74"&gt;&amp;#39;-&amp;#39;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt;|sort|uniq -c|wc -l
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;10000003&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;postgres@lzlhost /myhost/liuzhilong/pg_replslot/logical_ex9e15_rep&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ ll |wc -l
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;10000070&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;所以我们在实际环境中看到了10000070个文件，文件的distinct xid有10000003个，也就是说1个父事务跨越约70个wal文件，这个父事务有1000w个子事务。&lt;/p&gt;

&lt;h2 class="relative group"&gt;复制槽溢出测试
 &lt;div id="复制槽溢出测试" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%a4%8d%e5%88%b6%e6%a7%bd%e6%ba%a2%e5%87%ba%e6%b5%8b%e8%af%95" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--发布订阅搭建复制链路
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;logical_decoding_work_mem &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;64&lt;/span&gt;MB &lt;span style="color:#f92672"&gt;#&lt;/span&gt;pg_ctl reload
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;wal_segment_size &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;128&lt;/span&gt; MB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--source
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;CREATE&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;TABLE&lt;/span&gt; replication_table (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; id BIGSERIAL &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;KEY&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; column1 char(&lt;span style="color:#ae81ff"&gt;2000&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; column2 char(&lt;span style="color:#ae81ff"&gt;2000&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; column3 char(&lt;span style="color:#ae81ff"&gt;2000&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; publication pub_test &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; replication_table ;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--dest
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;CREATE&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;TABLE&lt;/span&gt; replication_table (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; id BIGSERIAL &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;KEY&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; column1 char(&lt;span style="color:#ae81ff"&gt;2000&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; column2 char(&lt;span style="color:#ae81ff"&gt;2000&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; column3 char(&lt;span style="color:#ae81ff"&gt;2000&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;CREATE&lt;/span&gt; SUBSCRIPTION sub_test
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;CONNECTION&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;host=127.0.0.1 port=8094 dbname=lzl user=lzl password=qwer&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PUBLICATION pub_test;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--source
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_replication_slots;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 class="relative group"&gt;大事务、无子事务、复制表溢出测试
 &lt;div id="大事务无子事务复制表溢出测试" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%a4%a7%e4%ba%8b%e5%8a%a1%e6%97%a0%e5%ad%90%e4%ba%8b%e5%8a%a1%e5%a4%8d%e5%88%b6%e8%a1%a8%e6%ba%a2%e5%87%ba%e6%b5%8b%e8%af%95" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--创建一个大事务暂时不提交
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;begin&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;insert&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;into&lt;/span&gt; replication_table(column1,column2,column3) 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;b&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;c&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; generate_series(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1000000&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;g&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--复制槽溢出
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ll
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;total &lt;span style="color:#ae81ff"&gt;331924&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;rw&lt;span style="color:#75715e"&gt;------- 1 postgres postgres 184 Dec 9 20:22 state
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;rw&lt;span style="color:#75715e"&gt;------- 1 postgres postgres 88226964 Dec 9 20:22 xid-5074343-lsn-163-38000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;rw&lt;span style="color:#75715e"&gt;------- 1 postgres postgres 119698488 Dec 9 20:22 xid-5074343-lsn-163-40000000.spill&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;大事务提交后，等待消费直至复制链路延迟为0，spill文件消失&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;M&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; pid,usename,sent_lsn,write_lsn,flush_lsn,replay_lsn,write_lag,flush_lag,replay_lag,reply_time &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_stat_replication;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; usename &lt;span style="color:#f92672"&gt;|&lt;/span&gt; sent_lsn &lt;span style="color:#f92672"&gt;|&lt;/span&gt; write_lsn &lt;span style="color:#f92672"&gt;|&lt;/span&gt; flush_lsn &lt;span style="color:#f92672"&gt;|&lt;/span&gt; replay_lsn &lt;span style="color:#f92672"&gt;|&lt;/span&gt; write_lag &lt;span style="color:#f92672"&gt;|&lt;/span&gt; flush_lag &lt;span style="color:#f92672"&gt;|&lt;/span&gt; replay_lag &lt;span style="color:#f92672"&gt;|&lt;/span&gt; reply_time 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--------+---------+--------------+--------------+--------------+--------------+-----------+-----------+------------+------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;163525&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzl &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;163&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4996&lt;/span&gt;E1C8 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;163&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4996&lt;/span&gt;E1C8 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;163&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4996&lt;/span&gt;E1C8 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;163&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4996&lt;/span&gt;E1C8 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;09&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;25&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;35&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14769&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;row&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;M&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; pid,usename,pg_wal_lsn_diff(pg_current_wal_lsn(),sent_lsn) diff_sent_mb,pg_wal_lsn_diff(pg_current_wal_lsn(),write_lsn) diff_write_mb,pg_wal_lsn_diff(pg_current_wal_lsn(),flush_lsn) diff_flush_mb,pg_wal_lsn_diff(pg_current_wal_lsn(),replay_lsn) diff_replay_mb,pg_walfile_name_offset(sent_lsn) sentoffset,pg_walfile_name_offset(write_lsn) writeoffset,pg_walfile_name_offset(flush_lsn) flush_lsn &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_stat_replication;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; usename &lt;span style="color:#f92672"&gt;|&lt;/span&gt; diff_sent_mb &lt;span style="color:#f92672"&gt;|&lt;/span&gt; diff_write_mb &lt;span style="color:#f92672"&gt;|&lt;/span&gt; diff_flush_mb &lt;span style="color:#f92672"&gt;|&lt;/span&gt; diff_replay_mb &lt;span style="color:#f92672"&gt;|&lt;/span&gt; sentoffset &lt;span style="color:#f92672"&gt;|&lt;/span&gt; writeoffset &lt;span style="color:#f92672"&gt;|&lt;/span&gt; flush_lsn 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--------+---------+--------------+---------------+---------------+----------------+-------------------------------------+-------------------------------------+-------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;163525&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzl &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;000000010000016300000009&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;26665416&lt;/span&gt;) &lt;span style="color:#f92672"&gt;|&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;000000010000016300000009&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;26665416&lt;/span&gt;) &lt;span style="color:#f92672"&gt;|&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;000000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[&lt;span style="color:#f92672"&gt;/&lt;/span&gt;mypg&lt;span style="color:#f92672"&gt;/&lt;/span&gt;pg8094&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;pg_replslot&lt;span style="color:#f92672"&gt;/&lt;/span&gt;sub_test]&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt; ll
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;total &lt;span style="color:#ae81ff"&gt;357392&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;rw&lt;span style="color:#75715e"&gt;------- 1 postgres postgres 184 Dec 9 20:23 state
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;rw&lt;span style="color:#75715e"&gt;------- 1 postgres postgres 88226964 Dec 9 20:22 xid-5074343-lsn-163-38000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;rw&lt;span style="color:#75715e"&gt;------- 1 postgres postgres 137696328 Dec 9 20:23 xid-5074343-lsn-163-40000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;rw&lt;span style="color:#75715e"&gt;------- 1 postgres postgres 26076708 Dec 9 20:23 xid-5074343-lsn-163-48000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[&lt;span style="color:#f92672"&gt;/&lt;/span&gt;mypg&lt;span style="color:#f92672"&gt;/&lt;/span&gt;pg8094&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;pg_replslot&lt;span style="color:#f92672"&gt;/&lt;/span&gt;sub_test]&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt; ll
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;total &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;rw&lt;span style="color:#75715e"&gt;------- 1 postgres postgres 184 Dec 9 20:25 state2666
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;row&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 class="relative group"&gt;大事务、无子事务、非复制表溢出测试
 &lt;div id="大事务无子事务非复制表溢出测试" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%a4%a7%e4%ba%8b%e5%8a%a1%e6%97%a0%e5%ad%90%e4%ba%8b%e5%8a%a1%e9%9d%9e%e5%a4%8d%e5%88%b6%e8%a1%a8%e6%ba%a2%e5%87%ba%e6%b5%8b%e8%af%95" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--source 创建一个不相干的表，准备写入数据
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;CREATE&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;TABLE&lt;/span&gt; no_replication_table (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; id BIGSERIAL &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;KEY&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; column1 char(&lt;span style="color:#ae81ff"&gt;2000&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; column2 char(&lt;span style="color:#ae81ff"&gt;2000&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; column3 char(&lt;span style="color:#ae81ff"&gt;2000&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--创建一个大事务暂时不提交
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;begin&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;insert&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;into&lt;/span&gt; no_replication_table(column1,column2,column3) 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;b&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;c&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; generate_series(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1000000&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;g&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--溢出
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[postgres&lt;span style="color:#f92672"&gt;@&lt;/span&gt;lzldb:MYINST:&lt;span style="color:#ae81ff"&gt;8094&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&lt;/span&gt;mypg&lt;span style="color:#f92672"&gt;/&lt;/span&gt;pg8094&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;pg_replslot&lt;span style="color:#f92672"&gt;/&lt;/span&gt;sub_test]&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt; ll
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;total &lt;span style="color:#ae81ff"&gt;357492&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;rw&lt;span style="color:#75715e"&gt;------- 1 postgres postgres 184 Dec 9 20:09 state
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;rw&lt;span style="color:#75715e"&gt;------- 1 postgres postgres 107511456 Dec 9 20:08 xid-5074106-lsn-163-28000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;rw&lt;span style="color:#75715e"&gt;------- 1 postgres postgres 137698804 Dec 9 20:09 xid-5074106-lsn-163-30000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;rw&lt;span style="color:#75715e"&gt;------- 1 postgres postgres 4308444 Dec 9 20:09 xid-5074106-lsn-163-38000000.spill&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 class="relative group"&gt;大事务、子事务、非复制表溢出测试
 &lt;div id="大事务子事务非复制表溢出测试" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%a4%a7%e4%ba%8b%e5%8a%a1%e5%ad%90%e4%ba%8b%e5%8a%a1%e9%9d%9e%e5%a4%8d%e5%88%b6%e8%a1%a8%e6%ba%a2%e5%87%ba%e6%b5%8b%e8%af%95" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## 一次insert一行，每个insert一个子事务&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;echo &lt;span style="color:#e6db74"&gt;&amp;#34;begin;&amp;#34;&lt;/span&gt;&amp;gt;subtx.sql
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i in &lt;span style="color:#f92672"&gt;{&lt;/span&gt;1..1000000&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;savepoint p&lt;/span&gt;$i&lt;span style="color:#e6db74"&gt;;&amp;#34;&lt;/span&gt;&amp;gt;&amp;gt;subtx.sql
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;insert into no_replication_table(column1,column2,column3) select &amp;#39;a&amp;#39;,&amp;#39;b&amp;#39;,&amp;#39;c&amp;#39;;&amp;#34;&lt;/span&gt;&amp;gt;&amp;gt;subtx.sql
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nohup psql -d lzl -f subtx.sql &amp;amp;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#执行过程中，观察到溢出80w+文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;/myhost/pg8094/data/pg_replslot/sub_test&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ ll |wc -l
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;823749&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;/myhost/pg8094/data/pg_replslot/sub_test&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ ll |head -10
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;total &lt;span style="color:#ae81ff"&gt;1099532&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;184&lt;/span&gt; Dec &lt;span style="color:#ae81ff"&gt;9&lt;/span&gt; 21:10 state
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;1236&lt;/span&gt; Dec &lt;span style="color:#ae81ff"&gt;9&lt;/span&gt; 21:10 xid-5519686-lsn-163-70000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;252&lt;/span&gt; Dec &lt;span style="color:#ae81ff"&gt;9&lt;/span&gt; 21:09 xid-5519687-lsn-163-70000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;252&lt;/span&gt; Dec &lt;span style="color:#ae81ff"&gt;9&lt;/span&gt; 21:09 xid-5519688-lsn-163-70000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;252&lt;/span&gt; Dec &lt;span style="color:#ae81ff"&gt;9&lt;/span&gt; 21:09 xid-5519689-lsn-163-70000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;252&lt;/span&gt; Dec &lt;span style="color:#ae81ff"&gt;9&lt;/span&gt; 21:09 xid-5519690-lsn-163-70000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;252&lt;/span&gt; Dec &lt;span style="color:#ae81ff"&gt;9&lt;/span&gt; 21:09 xid-5519691-lsn-163-70000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;252&lt;/span&gt; Dec &lt;span style="color:#ae81ff"&gt;9&lt;/span&gt; 21:09 xid-5519692-lsn-163-70000000.spill
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;252&lt;/span&gt; Dec &lt;span style="color:#ae81ff"&gt;9&lt;/span&gt; 21:09 xid-5519693-lsn-163-70000000.spill&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 class="relative group"&gt;数据库启动慢分析
 &lt;div id="数据库启动慢分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%95%b0%e6%8d%ae%e5%ba%93%e5%90%af%e5%8a%a8%e6%85%a2%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;startup进程起库流程分析
 &lt;div id="startup进程起库流程分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#startup%e8%bf%9b%e7%a8%8b%e8%b5%b7%e5%ba%93%e6%b5%81%e7%a8%8b%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;这里以堆栈编号逐栈解析起库流程：&lt;/p&gt;
&lt;p&gt;11：&lt;code&gt;main&lt;/code&gt;：没啥好说的&lt;/p&gt;
&lt;p&gt;10：&lt;code&gt;PostmasterMain&lt;/code&gt;：&lt;/p&gt;
&lt;p&gt;在主循环前，会先调用起库流程&lt;code&gt; StartupPID = StartupDataBase();&lt;/code&gt;本质上是调用&lt;code&gt;StartChildProcess(StartupProcess)&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define StartupDataBase()		StartChildProcess(StartupProcess)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;9：&lt;code&gt;StartChildProcess&lt;/code&gt; ：fork一个进程。该进程为启动postmaster的辅助进程，正常的子进程启动都走这个逻辑，在这一步fork。这里的入参&lt;code&gt;AuxProcType&lt;/code&gt;=StartupProcess&lt;/p&gt;
&lt;p&gt;8：&lt;code&gt;AuxiliaryProcessMain&lt;/code&gt;：&lt;/p&gt;
&lt;p&gt;因为&lt;code&gt;MyAuxProcType&lt;/code&gt;=StartupProcess，所以走的是&lt;code&gt;StartupProcessMain&lt;/code&gt;流程，这不同于&lt;strong&gt;walsender&lt;/strong&gt;,walwrite,bgwriter这些子进程的流程。startup进程本身是为了宕机恢复读wal的进程，但是它还做了很多事情&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; (MyAuxProcType)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; CheckerProcess:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/* don&amp;#39;t set signals, they&amp;#39;re useless here */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;CheckerModeMain&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;proc_exit&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;);		&lt;span style="color:#75715e"&gt;/* should never return */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; BootstrapProcess:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * There was a brief instant during which mode was Normal; this is
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * okay. We need to be in bootstrap mode during BootStrapXLOG for
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * the sake of multixact initialization.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;SetProcessingMode&lt;/span&gt;(BootstrapProcessing);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;bootstrap_signals&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;BootStrapXLOG&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;BootstrapModeMain&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;proc_exit&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;);		&lt;span style="color:#75715e"&gt;/* should never return */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; StartupProcess: &lt;span style="color:#75715e"&gt;//这里这里这里这里
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/* don&amp;#39;t set signals, startup process has its own agenda */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;StartupProcessMain&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;proc_exit&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;);		&lt;span style="color:#75715e"&gt;/* should never return */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; BgWriterProcess:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/* don&amp;#39;t set signals, bgwriter has its own agenda */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;BackgroundWriterMain&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;proc_exit&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;);		&lt;span style="color:#75715e"&gt;/* should never return */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; CheckpointerProcess:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/* don&amp;#39;t set signals, checkpointer has its own agenda */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;CheckpointerMain&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;proc_exit&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;);		&lt;span style="color:#75715e"&gt;/* should never return */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; WalWriterProcess:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/* don&amp;#39;t set signals, walwriter has its own agenda */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;InitXLOGAccess&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;WalWriterMain&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;proc_exit&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;);		&lt;span style="color:#75715e"&gt;/* should never return */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; WalReceiverProcess:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/* don&amp;#39;t set signals, walreceiver has its own agenda */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;WalReceiverMain&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;proc_exit&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;);		&lt;span style="color:#75715e"&gt;/* should never return */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;default&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;elog&lt;/span&gt;(PANIC, &lt;span style="color:#e6db74"&gt;&amp;#34;unrecognized process type: %d&amp;#34;&lt;/span&gt;, (&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) MyAuxProcType);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;proc_exit&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;7：&lt;code&gt;StartupProcessMain&lt;/code&gt;：主要是为了调用&lt;code&gt;StartupXLOG()&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;6：&lt;code&gt;StartupXLOG&lt;/code&gt;：&lt;/p&gt;
&lt;p&gt;函数注释：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;This must be called ONCE during postmaster or standalone&lt;span style="color:#f92672"&gt;-&lt;/span&gt;backend startup&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;StartupXLOG&lt;/code&gt;无论怎样都会被postmaster调用，无论是否是崩溃停库还是一致性停库&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; (ControlFile&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;state)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; DB_IN_PRODUCTION:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;ereport&lt;/span&gt;(LOG,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					(&lt;span style="color:#a6e22e"&gt;errmsg&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;database system was interrupted; last known up at %s&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;							&lt;span style="color:#a6e22e"&gt;str_time&lt;/span&gt;(ControlFile&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;time))));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这跟log日志能对上，以下是log的停库起库输出：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:02:57.534 CST,,,447560,,65693cde.6d448,1325,,2023-12-01 09:54:38 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;database system is shut down&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;postmaster&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:03:49.536 CST,,,211844,,6752bdf3.33b84,1,,2024-12-06 17:03:47 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;ending log output to stderr&amp;#34;&lt;/span&gt;,,&lt;span style="color:#e6db74"&gt;&amp;#34;Future log output will go to log destination &amp;#34;&amp;#34;csvlog&amp;#34;&amp;#34;.&amp;#34;&lt;/span&gt;,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;postmaster&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:03:49.536 CST,,,211844,,6752bdf3.33b84,2,,2024-12-06 17:03:47 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;starting PostgreSQL 13.2 (RaseSQL 1.3) on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39.0.1), 64-bit&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;postmaster&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:03:49.537 CST,,,211844,,6752bdf3.33b84,3,,2024-12-06 17:03:47 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;listening on IPv4 address &amp;#34;&amp;#34;0.0.0.0&amp;#34;&amp;#34;, port 7284&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;postmaster&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:03:49.539 CST,,,211844,,6752bdf3.33b84,4,,2024-12-06 17:03:47 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;listening on Unix socket &amp;#34;&amp;#34;/tmp/.s.PGSQL.7284&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;postmaster&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:03:49.557 CST,,,211995,,6752bdf5.33c1b,1,,2024-12-06 17:03:49 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;database system was interrupted; last known up at 2024-12-06 17:00:10 CST&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;startup&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;所以，当时停库后，控制文件记录的数据库状态为&lt;code&gt;in production&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Database cluster state: in production&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;in production&lt;/code&gt;这个状态是&lt;strong&gt;数据库正在运行&lt;/strong&gt;，而不是正常的shutdown状态，说明当时数据库停库时&lt;strong&gt;不是一致性停库&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;继续其中关于fsync的关键代码：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*----------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * If we previously crashed, perform a couple of actions:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * - The pg_wal directory may still include some temporary WAL segments
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * used when creating a new segment, so perform some clean up to not
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * bloat this path. This is done first as there is no point to sync
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * this temporary data.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * - There might be data which we had written, intending to fsync it, but
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * which we had not actually fsync&amp;#39;d yet. Therefore, a power failure in
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * the near future might cause earlier unflushed writes to be lost, even
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * though more recent data written to disk from here on would be
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * persisted. To avoid that, fsync the entire data directory.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (ControlFile&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;state &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; DB_SHUTDOWNED &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		ControlFile&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;state &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; DB_SHUTDOWNED_IN_RECOVERY)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;RemoveTempXlogFiles&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;SyncDataDirectory&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这里因为控制文件记录的状态不是正常停库的，所以走到if中调用&lt;code&gt;SyncDataDirectory()&lt;/code&gt;做fsync持久化。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;StartupXLOG&lt;/code&gt;做了很多很多事，其中跟spill相关的除了&lt;code&gt;SyncDataDirectory()&lt;/code&gt;还有&lt;code&gt;StartupReorderBuffer()&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * Initialize replication slots, before there&amp;#39;s a chance to remove
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * required resources.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;StartupReplicationSlots&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * Startup logical state, needs to be setup now so we have proper data
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * during crash recovery.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;StartupReorderBuffer&lt;/span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;StartupReorderBuffer&lt;/code&gt;虽然也会被调用，它会调用&lt;code&gt;ReorderBufferCleanupSerializedTXNs&lt;/code&gt;清理所有slot目录的spill文件（不是删除目录和state文件）&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Delete all data spilled to disk after we&amp;#39;ve restarted/crashed. It will be
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * recreated when the respective slots are reused.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;StartupReorderBuffer&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	DIR		 &lt;span style="color:#f92672"&gt;*&lt;/span&gt;logical_dir;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; dirent &lt;span style="color:#f92672"&gt;*&lt;/span&gt;logical_de;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	logical_dir &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AllocateDir&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;pg_replslot&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; ((logical_de &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ReadDir&lt;/span&gt;(logical_dir, &lt;span style="color:#e6db74"&gt;&amp;#34;pg_replslot&amp;#34;&lt;/span&gt;)) &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; NULL)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;strcmp&lt;/span&gt;(logical_de&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;d_name, &lt;span style="color:#e6db74"&gt;&amp;#34;.&amp;#34;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;strcmp&lt;/span&gt;(logical_de&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;d_name, &lt;span style="color:#e6db74"&gt;&amp;#34;..&amp;#34;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;continue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* if it cannot be a slot, skip the directory */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;ReplicationSlotValidateName&lt;/span&gt;(logical_de&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;d_name, DEBUG2))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;continue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * ok, has to be a surviving logical slot, iterate and delete
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * everything starting with xid-*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;ReorderBufferCleanupSerializedTXNs&lt;/span&gt;(logical_de&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;d_name);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;FreeDir&lt;/span&gt;(logical_dir);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;5：&lt;code&gt;SyncDataDirectory&lt;/code&gt;：&lt;/p&gt;
&lt;p&gt;这段函数注释非常重要：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Issue fsync recursively on PGDATA and all its contents.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * We fsync regular files and directories wherever they are, but we
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * follow symlinks only for pg_wal and immediately under pg_tblspc.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Other symlinks are presumed to point at files we&amp;#39;re not responsible
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * for fsyncing, and might not have privileges to write at all.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Errors are logged but not considered fatal; that&amp;#39;s because this is used
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * only during database startup, to deal with the possibility that there are
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * issued-but-unsynced writes pending against the data directory. We want to
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * ensure that such writes reach disk before anything that&amp;#39;s done in the new
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * run. However, aborting on error would result in failure to start for
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * harmless cases such as read-only files in the data directory, and that&amp;#39;s
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * not good either.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Note that if we previously crashed due to a PANIC on fsync(), we&amp;#39;ll be
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * rewriting all changes again during recovery.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Note we assume we&amp;#39;re chdir&amp;#39;d into PGDATA to begin with.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;fsync所有data目录文件使之持久化&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;这个动作只会发生在起库阶段&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;这个动作是为了保证在数据库运行前data目录是完全持久化的&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;SyncDataDirectory&lt;/code&gt;主体是递归遍历目录并fsync（link文件稍微特殊处理一下）：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;walkdir&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;.&amp;#34;&lt;/span&gt;, datadir_fsync_fname, false, LOG);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (xlog_is_symlink)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;walkdir&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;pg_wal&amp;#34;&lt;/span&gt;, datadir_fsync_fname, false, LOG);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;walkdir&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;pg_tblspc&amp;#34;&lt;/span&gt;, datadir_fsync_fname, true, LOG);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;4：&lt;code&gt;walkdir&lt;/code&gt;：递归到&lt;code&gt;.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;3：&lt;code&gt;walkdir&lt;/code&gt;：递归到&lt;code&gt;./pg_replslot&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;2：&lt;code&gt;walkdir&lt;/code&gt;：递归到&lt;code&gt;./pg_replslot/slotname&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;1：&lt;code&gt;lstat&lt;/code&gt; ：C库调用。&lt;code&gt;walkdir&lt;/code&gt;不仅要做fsync（入参函数&lt;code&gt;datadir_fsync_fname&lt;/code&gt;），&lt;code&gt;walkdir&lt;/code&gt;函数本体还要做 &lt;code&gt;lstat&lt;/code&gt;获取文件信息，如inode、文件大小、最近修改时间等等，类似linux的&lt;code&gt;stat&lt;/code&gt;命令。&lt;/p&gt;
&lt;p&gt;0：&lt;code&gt;_lxstat&lt;/code&gt;：C库调用&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;起库逻辑汇总&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pg会启动一个辅助进程&lt;code&gt;startup&lt;/code&gt;以协助起库，不同于在常见的childprocess（walwriter、bgwriter、checkpointer等等）进程，它是起库过程中必定会启动的进程，它会做很多事情&lt;/li&gt;
&lt;li&gt;&lt;code&gt;StartupXLOG&lt;/code&gt;起库时一定会被调用，无论数据库是否一致性停库&lt;/li&gt;
&lt;li&gt;只有非正常停库状态下，才会触发&lt;code&gt;SyncDataDirectory&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SyncDataDirectory&lt;/code&gt;会fsync持久化所有data文件，并查看所有data文件的stat信息&lt;/li&gt;
&lt;li&gt;fsync是为了在库启动前保证data文件都一致；stat应该是为了验证文件是否正常和可读（在startup进程启动前只验证过datadir目录可读性）&lt;/li&gt;
&lt;li&gt;无论停库状态，&lt;code&gt;StartupReorderBuffer&lt;/code&gt;一定会被调用并清理所有复制槽的spill文件&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;什么时候是ready状态
 &lt;div id="什么时候是ready状态" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%bb%80%e4%b9%88%e6%97%b6%e5%80%99%e6%98%afready%e7%8a%b6%e6%80%81" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;startup进程把活干完后数据库还不是ready状态，在pmState状态机改变状态时会调用&lt;code&gt;reaper&lt;/code&gt;回收进程函数。reaper函数本身是为了子进程退出后进行一些回收或者启动工作。pmState状态机记录状态为PM_STARTUP，状态机是控制启停库状态的。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;PostmasterMain&lt;/code&gt;的最后几步：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	StartupPID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;StartupDataBase&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;Assert&lt;/span&gt;(StartupPID &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	StartupStatus &lt;span style="color:#f92672"&gt;=&lt;/span&gt; STARTUP_RUNNING;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	pmState &lt;span style="color:#f92672"&gt;=&lt;/span&gt; PM_STARTUP; &lt;span style="color:#75715e"&gt;//状态机改变状态
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/* Some workers may be scheduled to start now */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;maybe_start_bgworkers&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	status &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ServerLoop&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * ServerLoop probably shouldn&amp;#39;t ever return, but if it does, close down.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;ExitPostmaster&lt;/span&gt;(status &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; STATUS_OK);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;abort&lt;/span&gt;();					&lt;span style="color:#75715e"&gt;/* not reached */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;PostmasterMain&lt;/code&gt;起库的核心流程会走到&lt;code&gt;reaper&lt;/code&gt;以处理startup进程的正常退出，&lt;/p&gt;
&lt;p&gt;PMState注释：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * We use a simple state machine to control startup, shutdown, and
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * crash recovery (which is rather like shutdown followed by startup).
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * After doing all the postmaster initialization work, we enter PM_STARTUP
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * state and the startup process is launched. The startup process begins by
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * reading the control file and other preliminary initialization steps.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * In a normal startup, or after crash recovery, the startup process exits
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * with exit code 0 and we switch to PM_RUN state. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;PMState会被信号传递和处理，startup进程退出后&lt;code&gt;reaper&lt;/code&gt;会被激活以回收进程。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;reaper&lt;/code&gt;函数处理startup子进程的正常退出态：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (pid &lt;span style="color:#f92672"&gt;==&lt;/span&gt; StartupPID)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			StartupPID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * Startup succeeded, commence normal operations
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			StartupStatus &lt;span style="color:#f92672"&gt;=&lt;/span&gt; STARTUP_NOT_RUNNING; &lt;span style="color:#75715e"&gt;//由STARTUP_RUNNING转成STARTUP_NOT_RUNNING
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			FatalError &lt;span style="color:#f92672"&gt;=&lt;/span&gt; false; &lt;span style="color:#75715e"&gt;//上面一堆if未命中后，才不是fatal的
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			AbortStartTime &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			ReachedNormalRunning &lt;span style="color:#f92672"&gt;=&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			pmState &lt;span style="color:#f92672"&gt;=&lt;/span&gt; PM_RUN; &lt;span style="color:#75715e"&gt;//状态机由PM_STARTUP转成PM_RUN
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			connsAllowed &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ALLOW_ALL_CONNS;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * Crank up the background tasks, if we didn&amp;#39;t do that already
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * when we entered consistent recovery state. It doesn&amp;#39;t matter
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * if this fails, we&amp;#39;ll just try again later.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//以下都在启动核心子进程
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (CheckpointerPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				CheckpointerPID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;StartCheckpointer&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (BgWriterPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				BgWriterPID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;StartBackgroundWriter&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (WalWriterPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				WalWriterPID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;StartWalWriter&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * Likewise, start other special children as needed. In a restart
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * situation, some of them may be alive already.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//以下都在启动非核心子进程
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;IsBinaryUpgrade &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AutoVacuumingActive&lt;/span&gt;() &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; AutoVacPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				AutoVacPID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;StartAutoVacLauncher&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;PgArchStartupAllowed&lt;/span&gt;() &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; PgArchPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				PgArchPID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pgarch_start&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (PgStatPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				PgStatPID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pgstat_start&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/* workers may be scheduled to start now */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;maybe_start_bgworkers&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		 &lt;span style="color:#75715e"&gt;//此时才是正式的可接受连接状态
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/* at this point we are really open for business */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;ereport&lt;/span&gt;(LOG,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					(&lt;span style="color:#a6e22e"&gt;errmsg&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;database system is ready to accept connections&amp;#34;&lt;/span&gt;)));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/* Report status */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;AddToDataDirLockFile&lt;/span&gt;(LOCK_FILE_LINE_PM_STATUS, PM_STATUS_READY);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#ifdef USE_SYSTEMD
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;sd_notify&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;READY=1&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#endif
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;continue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;“database system is ready to accept connections”信息就在这里了&lt;/p&gt;
&lt;p&gt;checkpointer、bgwrite、walwrite、autovacuum、arch（如有）、stat这些进程都需要启动，在这个阶段拉起这些进程不是必须返回成功的，后续也可以在&lt;code&gt;ServerLoop&lt;/code&gt;或者再次执行&lt;code&gt;reaper&lt;/code&gt;时尝试启动，只有startup进程是必须一次性必须启动并完成所有相关任务的：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (pid &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* in parent, fork failed */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;			save_errno &lt;span style="color:#f92672"&gt;=&lt;/span&gt; errno;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		errno &lt;span style="color:#f92672"&gt;=&lt;/span&gt; save_errno;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; (type)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; StartupProcess:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;ereport&lt;/span&gt;(LOG,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						(&lt;span style="color:#a6e22e"&gt;errmsg&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;could not fork startup process: %m&amp;#34;&lt;/span&gt;)));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; BgWriterProcess:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;ereport&lt;/span&gt;(LOG,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						(&lt;span style="color:#a6e22e"&gt;errmsg&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;could not fork background writer process: %m&amp;#34;&lt;/span&gt;)));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; CheckpointerProcess:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;ereport&lt;/span&gt;(LOG,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						(&lt;span style="color:#a6e22e"&gt;errmsg&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;could not fork checkpointer process: %m&amp;#34;&lt;/span&gt;)));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; WalWriterProcess:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;ereport&lt;/span&gt;(LOG,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						(&lt;span style="color:#a6e22e"&gt;errmsg&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;could not fork WAL writer process: %m&amp;#34;&lt;/span&gt;)));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; WalReceiverProcess:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;ereport&lt;/span&gt;(LOG,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						(&lt;span style="color:#a6e22e"&gt;errmsg&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;could not fork WAL receiver process: %m&amp;#34;&lt;/span&gt;)));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;default&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;ereport&lt;/span&gt;(LOG,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						(&lt;span style="color:#a6e22e"&gt;errmsg&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;could not fork process: %m&amp;#34;&lt;/span&gt;)));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * fork failure is fatal during startup, but there&amp;#39;s no need to choke
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * immediately if starting other child types fails.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (type &lt;span style="color:#f92672"&gt;==&lt;/span&gt; StartupProcess)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;ExitPostmaster&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 class="relative group"&gt;spill文件生成逻辑各版本差异
 &lt;div id="spill文件生成逻辑各版本差异" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#spill%e6%96%87%e4%bb%b6%e7%94%9f%e6%88%90%e9%80%bb%e8%be%91%e5%90%84%e7%89%88%e6%9c%ac%e5%b7%ae%e5%bc%82" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;spill在各个版本都是spill最大的事务，这里重点关注啥时候spill的逻辑&lt;/p&gt;
&lt;p&gt;PG12：pg12的changes是4096条写死&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; Size max_changes_in_memory &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Check whether the transaction tx should spill its data to disk.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;ReorderBufferCheckSerializeTXN&lt;/span&gt;(ReorderBuffer &lt;span style="color:#f92672"&gt;*&lt;/span&gt;rb, ReorderBufferTXN &lt;span style="color:#f92672"&gt;*&lt;/span&gt;txn)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * TODO: improve accounting so we cheaply can take subtransactions into
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * account here.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (txn&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;nentries_mem &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; max_changes_in_memory)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;ReorderBufferSerializeTXN&lt;/span&gt;(rb, txn);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;Assert&lt;/span&gt;(txn&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;nentries_mem &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;PG13:超过&lt;code&gt;logical_decoding_work_mem&lt;/code&gt;内存大小就spill&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;ReorderBufferCheckMemoryLimit&lt;/span&gt;(ReorderBuffer &lt;span style="color:#f92672"&gt;*&lt;/span&gt;rb)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; (rb&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;size &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; logical_decoding_work_mem &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1024L&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * Pick the largest transaction (or subtransaction) and evict it from
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * memory by serializing it to disk.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		txn &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ReorderBufferLargestTXN&lt;/span&gt;(rb);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;ReorderBufferSerializeTXN&lt;/span&gt;(rb, txn);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;PG14：多个了一个流式传输ReorderBufferStreamTXN&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;ReorderBufferCheckMemoryLimit&lt;/span&gt;(ReorderBuffer &lt;span style="color:#f92672"&gt;*&lt;/span&gt;rb)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; (rb&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;size &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; logical_decoding_work_mem &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1024L&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * Pick the largest transaction (or subtransaction) and evict it from
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * memory by streaming, if possible. Otherwise, spill to disk.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;ReorderBufferCanStartStreaming&lt;/span&gt;(rb) &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			(txn &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ReorderBufferLargestTopTXN&lt;/span&gt;(rb)) &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; NULL)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;ReorderBufferStreamTXN&lt;/span&gt;(rb, txn);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;ReorderBufferSerializeTXN&lt;/span&gt;(rb, txn);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;14虽然有了流式复制，但是触发是要一定条件的：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/* Returns true, if the streaming can be started now, false, otherwise. */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;inline&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;ReorderBufferCanStartStreaming&lt;/span&gt;(ReorderBuffer &lt;span style="color:#f92672"&gt;*&lt;/span&gt;rb)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	LogicalDecodingContext &lt;span style="color:#f92672"&gt;*&lt;/span&gt;ctx &lt;span style="color:#f92672"&gt;=&lt;/span&gt; rb&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;private_data;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	SnapBuild &lt;span style="color:#f92672"&gt;*&lt;/span&gt;builder &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ctx&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;snapshot_builder;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/* We can&amp;#39;t start streaming unless a consistent state is reached. */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;SnapBuildCurrentState&lt;/span&gt;(builder) &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; SNAPBUILD_CONSISTENT)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; false;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * We can&amp;#39;t start streaming immediately even if the streaming is enabled
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * because we previously decoded this transaction and now just are
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * restarting.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;ReorderBufferCanStream&lt;/span&gt;(rb) &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SnapBuildXactNeedsSkip&lt;/span&gt;(builder, ctx&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;reader&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;EndRecPtr))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; false;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * Found a point after SNAPBUILD_FULL_SNAPSHOT where all transactions that
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * were running at that point finished. Till we reach that we hold off
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * calling any commit callbacks.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	SNAPBUILD_CONSISTENT &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;额外的steam触发条件：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;条件1：快照中的事务涵盖的所有事务都已完成（应该指commit or rollback）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;条件2：context是私有数据（是不是说两条链路一张表就不会触发steam？）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;条件3：快照中的事务是不可忽略的事务（可能指特殊的事务可以忽略，就不做了）&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;PG15：跟14差不多，只是函数更清晰，套娃少一些了&lt;/p&gt;
&lt;p&gt;PG16：差不多&lt;/p&gt;
&lt;p&gt;PG17：差不多，新增一个&lt;code&gt;DEBUG_LOGICAL_REP_STREAMING_IMMEDIATE&lt;/code&gt;可以强制stream&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;记忆点：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PG12及以前是写死的4096条changes&lt;/li&gt;
&lt;li&gt;PG13新增&lt;code&gt;logical_decoding_work_mem&lt;/code&gt;参数，可调整内存大小以减少spill概率&lt;/li&gt;
&lt;li&gt;PG14及以后支持流式复制Streaming&lt;/li&gt;
&lt;li&gt;触发流式复制也需要一定的条件，所以即使有流式复制也可能会发生spill&lt;/li&gt;
&lt;li&gt;PG17新增&lt;code&gt;debug_logical_replication_streaming&lt;/code&gt;参数以强制触发流式传输&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;spill文件清理逻辑
 &lt;div id="spill文件清理逻辑" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#spill%e6%96%87%e4%bb%b6%e6%b8%85%e7%90%86%e9%80%bb%e8%be%91" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;起库时清理spill其实只是一种场景，还有启动walsender清理和drop slot清理。&lt;/p&gt;

&lt;h3 class="relative group"&gt;walsender启动时清理
 &lt;div id="walsender启动时清理" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#walsender%e5%90%af%e5%8a%a8%e6%97%b6%e6%b8%85%e7%90%86" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;ReorderBufferCleanupSerializedTXNs&lt;/code&gt;会在数据库启动（walsender还没有启动）、walsender启动（数据库运行中）时被调用，注意这两部分场景是不一样的，只是他们会调用同一个函数。从函数注释部分也可以看出，该函数是为了“删除残留的序列化的reorder buffers”，即清理spill文件。&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Remove any leftover serialized reorder buffers from a slot directory after a
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * prior crash or decoding session exit.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;ReorderBufferCleanupSerializedTXNs&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;char&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;slotname)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	DIR		 &lt;span style="color:#f92672"&gt;*&lt;/span&gt;spill_dir;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; dirent &lt;span style="color:#f92672"&gt;*&lt;/span&gt;spill_de;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; stat statbuf;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;char&lt;/span&gt;		path[MAXPGPATH &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;sprintf&lt;/span&gt;(path, &lt;span style="color:#e6db74"&gt;&amp;#34;pg_replslot/%s&amp;#34;&lt;/span&gt;, slotname);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/* we&amp;#39;re only handling directories here, skip if it&amp;#39;s not ours */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;lstat&lt;/span&gt;(path, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;statbuf) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;S_ISDIR&lt;/span&gt;(statbuf.st_mode))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	spill_dir &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AllocateDir&lt;/span&gt;(path);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; ((spill_de &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ReadDirExtended&lt;/span&gt;(spill_dir, path, INFO)) &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; NULL)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* only look at names that can be ours */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//只对比前3个字符
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;strncmp&lt;/span&gt;(spill_de&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;d_name, &lt;span style="color:#e6db74"&gt;&amp;#34;xid&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;snprintf&lt;/span&gt;(path, &lt;span style="color:#66d9ef"&gt;sizeof&lt;/span&gt;(path),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					 &lt;span style="color:#e6db74"&gt;&amp;#34;pg_replslot/%s/%s&amp;#34;&lt;/span&gt;, slotname,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					 spill_de&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;d_name);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;unlink&lt;/span&gt;(path) &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;ereport&lt;/span&gt;(ERROR,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						(&lt;span style="color:#a6e22e"&gt;errcode_for_file_access&lt;/span&gt;(),mkdir 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						 &lt;span style="color:#a6e22e"&gt;errmsg&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;could not remove file &lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;%s&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt; during removal of pg_replslot/%s/xid*: %m&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;								path, slotname)));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;FreeDir&lt;/span&gt;(spill_dir);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;以上清理逻辑需要注意两点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;清理文件名以“xid”开头的文件。很明显state文件是不能清理的&lt;/li&gt;
&lt;li&gt;unlink清理，一次清理一个文件。考虑这一点可以帮助我们构建加速起库方案&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;数据库启动时清理
 &lt;div id="数据库启动时清理" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%95%b0%e6%8d%ae%e5%ba%93%e5%90%af%e5%8a%a8%e6%97%b6%e6%b8%85%e7%90%86" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;数据库启动时会fork一个startup进程来清理slot，清理函数跟walsender调用的清理函数一致：&lt;code&gt;ReorderBufferCleanupSerializedTXNs&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;还有一个区别在于，walsender重启后，只会清理当前同名slot spill；而数据库启动时会顺序清理所有slot spill。&lt;/p&gt;
&lt;p&gt;数据库启动startup进程，while顺序清理逻辑：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;StartupReorderBuffer&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	DIR		 &lt;span style="color:#f92672"&gt;*&lt;/span&gt;logical_dir;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; dirent &lt;span style="color:#f92672"&gt;*&lt;/span&gt;logical_de;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	logical_dir &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AllocateDir&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;pg_replslot&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; ((logical_de &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ReadDir&lt;/span&gt;(logical_dir, &lt;span style="color:#e6db74"&gt;&amp;#34;pg_replslot&amp;#34;&lt;/span&gt;)) &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; NULL)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{	&lt;span style="color:#75715e"&gt;//排除.和..
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;strcmp&lt;/span&gt;(logical_de&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;d_name, &lt;span style="color:#e6db74"&gt;&amp;#34;.&amp;#34;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;strcmp&lt;/span&gt;(logical_de&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;d_name, &lt;span style="color:#e6db74"&gt;&amp;#34;..&amp;#34;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;continue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;//验证slotname是否规范
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* if it cannot be a slot, skip the directory */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;ReplicationSlotValidateName&lt;/span&gt;(logical_de&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;d_name, DEBUG2))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;continue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * ok, has to be a surviving logical slot, iterate and delete
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * everything starting with xid-*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;ReorderBufferCleanupSerializedTXNs&lt;/span&gt;(logical_de&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;d_name);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;FreeDir&lt;/span&gt;(logical_dir);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;while循环调用&lt;code&gt;ReorderBufferCleanupSerializedTXNs&lt;/code&gt;，后面跟walsender启动清理逻辑就一样了。&lt;/p&gt;

&lt;h3 class="relative group"&gt;pg_drop_replication_slot手动清理
 &lt;div id="pg_drop_replication_slot手动清理" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#pg_drop_replication_slot%e6%89%8b%e5%8a%a8%e6%b8%85%e7%90%86" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;drop slot清理逻辑跟自动清理spill文件的逻辑&lt;strong&gt;不一样&lt;/strong&gt;，它没有调用到&lt;code&gt;ReorderBufferCleanupSerializedTXNs&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;drop slot流程如下：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pg_drop_replication_slot(PG_FUNCTION_ARGS)&lt;/code&gt;-&amp;gt;&lt;code&gt;ReplicationSlotDrop(const char *name, bool nowait)&lt;/code&gt;-&amp;gt;&lt;code&gt;ReplicationSlotDropAcquired(void)&lt;/code&gt;-&amp;gt;&lt;code&gt;ReplicationSlotDropPtr&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ReplicationSlotDropPtr&lt;/code&gt;清理复制槽的逻辑也很有意思:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Permanently drop the replication slot which will be released by the point
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * this function returns.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;ReplicationSlotDropPtr&lt;/span&gt;(ReplicationSlot &lt;span style="color:#f92672"&gt;*&lt;/span&gt;slot)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;char&lt;/span&gt;		path[MAXPGPATH];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;char&lt;/span&gt;		tmppath[MAXPGPATH];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * If some other backend ran this code concurrently with us, we might try
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * to delete a slot with a certain name while someone else was trying to
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * create a slot with the same name.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;LWLockAcquire&lt;/span&gt;(ReplicationSlotAllocationLock, LW_EXCLUSIVE);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/* Generate pathnames. */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;sprintf&lt;/span&gt;(path, &lt;span style="color:#e6db74"&gt;&amp;#34;pg_replslot/%s&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;NameStr&lt;/span&gt;(slot&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;data.name));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;sprintf&lt;/span&gt;(tmppath, &lt;span style="color:#e6db74"&gt;&amp;#34;pg_replslot/%s.tmp&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;NameStr&lt;/span&gt;(slot&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;data.name));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * Rename the slot directory on disk, so that we&amp;#39;ll no longer recognize
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * this as a valid slot. Note that if this fails, we&amp;#39;ve got to mark the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * slot inactive before bailing out. If we&amp;#39;re dropping an ephemeral or a
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * temporary slot, we better never fail hard as the caller won&amp;#39;t expect
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * the slot to survive and this might get called during error handling.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;rename&lt;/span&gt;(path, tmppath) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) &lt;span style="color:#75715e"&gt;//rename文件
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * We need to fsync() the directory we just renamed and its parent to
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * make sure that our changes are on disk in a crash-safe fashion. If
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * fsync() fails, we can&amp;#39;t be sure whether the changes are on disk or
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * not. For now, we handle that by panicking;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * StartupReplicationSlots() will try to straighten it out after
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * restart.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//fsync持久化
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;START_CRIT_SECTION&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;fsync_fname&lt;/span&gt;(tmppath, true);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;fsync_fname&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;pg_replslot&amp;#34;&lt;/span&gt;, true);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;END_CRIT_SECTION&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * If removing the directory fails, the worst thing that will happen is
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * that the user won&amp;#39;t be able to create a new slot with the same name
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * until the next server restart. We warn about it, but that&amp;#39;s all.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;rmtree&lt;/span&gt;(tmppath, true))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;ereport&lt;/span&gt;(WARNING,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				(&lt;span style="color:#a6e22e"&gt;errmsg&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;could not remove directory &lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;%s&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;, tmppath)));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * We release this at the very end, so that nobody starts trying to create
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * a slot while we&amp;#39;re still cleaning up the detritus of the old one.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;LWLockRelease&lt;/span&gt;(ReplicationSlotAllocationLock);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;drop slot不是直接去复制槽目录下面去unlink，而是先把复制槽目录&lt;code&gt;slotname/&lt;/code&gt;rename成 &lt;code&gt;slotname.tmp/&lt;/code&gt;，然后再去做unlink目录下的文件，最后再删除 &lt;code&gt;slotname.tmp/&lt;/code&gt;目录本身。&lt;/p&gt;
&lt;p&gt;其中rmtree也是在循环unlink文件。&lt;/p&gt;

&lt;h2 class="relative group"&gt;复制槽溢出发生后加速起库方案测试
 &lt;div id="复制槽溢出发生后加速起库方案测试" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%a4%8d%e5%88%b6%e6%a7%bd%e6%ba%a2%e5%87%ba%e5%8f%91%e7%94%9f%e5%90%8e%e5%8a%a0%e9%80%9f%e8%b5%b7%e5%ba%93%e6%96%b9%e6%a1%88%e6%b5%8b%e8%af%95" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;1000w个spill删除起来肯定是很慢的，直接mv目录的话就非常快。但是直接mv需要注意mv后的名称和state文件，以及需要知道mv到底跳过了哪一个源码步骤。&lt;/p&gt;

&lt;h3 class="relative group"&gt;mv的名称注意事项
 &lt;div id="mv的名称注意事项" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#mv%e7%9a%84%e5%90%8d%e7%a7%b0%e6%b3%a8%e6%84%8f%e4%ba%8b%e9%a1%b9" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;由于是异常停库，startup进程会执行&lt;code&gt;SyncDataDirectory&lt;/code&gt;fsync和stat所有data文件，这一点是比较难绕过的。&lt;code&gt;SyncDataDirectory&lt;/code&gt;做完以后，才开始处理复制槽。处理复制槽时会调用&lt;code&gt;StartupReorderBuffer()&lt;/code&gt;-&amp;gt;&lt;code&gt;ReorderBufferCleanupSerializedTXNs&lt;/code&gt;全量清理spill文件。&lt;/p&gt;
&lt;p&gt;在进入清理前，会调用&lt;code&gt;ReplicationSlotValidateName&lt;/code&gt;校验复制槽名称的有效性，我们可以在&lt;code&gt;ReplicationSlotValidateName&lt;/code&gt;上做文章，以骗过startup进程跳过&lt;code&gt;ReorderBufferCleanupSerializedTXNs&lt;/code&gt;的过程。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ReplicationSlotValidateName&lt;/code&gt;规则：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;ReplicationSlotValidateName&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;char&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;name, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; elevel)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (cp &lt;span style="color:#f92672"&gt;=&lt;/span&gt; name; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;cp; cp&lt;span style="color:#f92672"&gt;++&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{ &lt;span style="color:#75715e"&gt;//关键规则在这里
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;((&lt;span style="color:#f92672"&gt;*&lt;/span&gt;cp &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;a&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;cp &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;z&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			 &lt;span style="color:#f92672"&gt;||&lt;/span&gt; (&lt;span style="color:#f92672"&gt;*&lt;/span&gt;cp &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;cp &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;9&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			 &lt;span style="color:#f92672"&gt;||&lt;/span&gt; (&lt;span style="color:#f92672"&gt;*&lt;/span&gt;cp &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;_&amp;#39;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;ereport&lt;/span&gt;(elevel,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					(&lt;span style="color:#a6e22e"&gt;errcode&lt;/span&gt;(ERRCODE_INVALID_NAME),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					 &lt;span style="color:#a6e22e"&gt;errmsg&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;replication slot name &lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;%s&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt; contains invalid character&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;							name),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					 &lt;span style="color:#a6e22e"&gt;errhint&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Replication slot names may only contain lower case letters, numbers, and the underscore character.&amp;#34;&lt;/span&gt;)));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; false;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;有效slot name只包含&lt;code&gt;a-z&lt;/code&gt;;&lt;code&gt;0-9&lt;/code&gt;;&lt;code&gt;_&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;所以rename时建议加个点&lt;code&gt;.&lt;/code&gt;，&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;建议&lt;/em&gt;&lt;code&gt;slotname.bak&lt;/code&gt;,&lt;code&gt;slotname.20241215&lt;/code&gt;等。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;不建议&lt;/em&gt;&lt;code&gt;slotnamebackup&lt;/code&gt;,&lt;code&gt;slotname20241215&lt;/code&gt;,&lt;code&gt;slotname_bak&lt;/code&gt;等等&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;不建议&lt;/em&gt;&lt;code&gt;.tmp&lt;/code&gt;后缀，slotname有&lt;code&gt;.tmp&lt;/code&gt;后缀有特殊含义&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最后rename后，要创建目录和拷贝state，不然启动的slot会表现的很反常（比如重复的slotname、自动生产一个slotname、删不到slot、下游起不来链路等等）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;汇总推荐mv操作如下：&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd pg_replslot
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mv slotname slotname.bak 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mkdir slotname
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cp slotname.bak/state slotname/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 class="relative group"&gt;起库时间对比
 &lt;div id="起库时间对比" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%b5%b7%e5%ba%93%e6%97%b6%e9%97%b4%e5%af%b9%e6%af%94" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;对比不同源码流程起库速度，看看手工mv/rm加速起库到底有没有意义。&lt;/p&gt;
&lt;p&gt;参考源码逻辑原理：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;正常停库，走fsync和stat&lt;/li&gt;
&lt;li&gt;异常停库，走fsync和stat；&lt;/li&gt;
&lt;li&gt;有效mv，将slotname目录命名为&lt;code&gt;.bak&lt;/code&gt;，不走unlink&lt;/li&gt;
&lt;li&gt;无效mv，将slotname目录命名为&lt;code&gt;_bak&lt;/code&gt;且spill文件命名为xid开头，走unlink&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;由于正常spill文件实在太慢，这里手工伪造slot目录和spill文件，总共50个slot，每个slot 40w个spill，总共2000w个spill来测试起库时间（用cp目录的方式要比cp文件、dd文件快很多）。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;编号&lt;/th&gt;
 &lt;th&gt;测试方案&lt;/th&gt;
 &lt;th&gt;起库时间&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;1&lt;/td&gt;
 &lt;td&gt;正常停库；起库不做fsync和stat，不做unlink&lt;/td&gt;
 &lt;td&gt;0.1秒&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;2&lt;/td&gt;
 &lt;td&gt;正常停库，无效mv；起库不做fsync和stat，做unlink&lt;/td&gt;
 &lt;td&gt;11分41秒&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;3&lt;/td&gt;
 &lt;td&gt;异常停库，有效mv；起库做fsync和stat，不做unlink&lt;/td&gt;
 &lt;td&gt;4分35秒&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;4&lt;/td&gt;
 &lt;td&gt;异常停库，无效mv；起库做fsync和stat，做unlink&lt;/td&gt;
 &lt;td&gt;32分2秒&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;5&lt;/td&gt;
 &lt;td&gt;异常停库，rm（创建slot目录并保留state）&lt;/td&gt;
 &lt;td&gt;13分04秒&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;对比方案3、5，理论上当时的场景我们有效mv可以做到4分钟左右起库，rm的话13分钟左右。（这是一个粗糙的对比，恢复环境已经观察到有些东西不一样了）&lt;/p&gt;</content:encoded></item><item><title>PG停库逻辑和walsender阻止停库问题分析</title><link>https://lastdba.com/2025/01/04/pg%E5%81%9C%E5%BA%93%E9%80%BB%E8%BE%91%E5%92%8Cwalsender%E9%98%BB%E6%AD%A2%E5%81%9C%E5%BA%93%E9%97%AE%E9%A2%98%E5%88%86%E6%9E%90/</link><pubDate>Sat, 04 Jan 2025 00:00:00 +0000</pubDate><guid>https://lastdba.com/2025/01/04/pg%E5%81%9C%E5%BA%93%E9%80%BB%E8%BE%91%E5%92%8Cwalsender%E9%98%BB%E6%AD%A2%E5%81%9C%E5%BA%93%E9%97%AE%E9%A2%98%E5%88%86%E6%9E%90/</guid><description>&lt;h2 class="relative group"&gt;walsender阻止停库现象
 &lt;div id="walsender阻止停库现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#walsender%e9%98%bb%e6%ad%a2%e5%81%9c%e5%ba%93%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;生产停库日志输出如下：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:00:02.036 CST,,,447560,,65693cde.6d448,1320,,2023-12-01 09:54:38 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;received fast shutdown request&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;postmaster&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:00:02.295 CST,,,447560,,65693cde.6d448,1322,,2023-12-01 09:54:38 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;background worker &amp;#34;&amp;#34;logical replication launcher&amp;#34;&amp;#34; (PID 448996) exited with exit code 1&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;postmaster&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:00:10.627 CST,,,448990,,65693ce0.6d9de,213833,,2023-12-01 09:54:40 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;checkpoint complete: wrote 426844 buffers (5.1%); 0 WAL file(s) added, 0 removed, 5 recycled; write=91.427 s, sync=0.055 s, total=91.508 s; sync files=761, longest=0.028 s, average=0.001 s; distance=2197531 kB, estimate=2680783 kB&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;checkpointer&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:00:10.628 CST,,,448990,,65693ce0.6d9de,213834,,2023-12-01 09:54:40 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;shutting down&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;checkpointer&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--checkpointer做完checkpoint，并处于shutting down状态，pm没有退出
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--160s后pm接收到immediate shutdown，由探活脚本触发
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:02:43.348 CST,,,447560,,65693cde.6d448,1323,,2023-12-01 09:54:38 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;received immediate shutdown request&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;postmaster&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:02:43.370 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;logicaluser&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,283840,&lt;span style="color:#e6db74"&gt;&amp;#34;10.33.77.159:39865&amp;#34;&lt;/span&gt;,6751a2dc.454c0,7,&lt;span style="color:#e6db74"&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;,2024-12-05 20:55:56 CST,89/847309655,0,WARNING,57P02,&lt;span style="color:#e6db74"&gt;&amp;#34;terminating connection because of crash of another server process&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;In a moment you should be able to reconnect to the database and repeat your command.&amp;#34;&lt;/span&gt;,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;Debezium Streaming&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;walsender&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:02:43.370 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;logicaluser&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,157641,&lt;span style="color:#e6db74"&gt;&amp;#34;10.33.77.159:39407&amp;#34;&lt;/span&gt;,67408354.267c9,7,&lt;span style="color:#e6db74"&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;,2024-11-22 21:12:52 CST,9/3193590104,0,WARNING,57P02,&lt;span style="color:#e6db74"&gt;&amp;#34;terminating connection because of crash of another server process&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;In a moment you should be able to reconnect to the database and repeat your command.&amp;#34;&lt;/span&gt;,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;Debezium Streaming&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;walsender&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:02:43.370 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;logicaluser&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,157916,&lt;span style="color:#e6db74"&gt;&amp;#34;10.33.77.159:57038&amp;#34;&lt;/span&gt;,67408356.268dc,7,&lt;span style="color:#e6db74"&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;,2024-11-22 21:12:54 CST,115/3293293502,0,WARNING,57P02,&lt;span style="color:#e6db74"&gt;&amp;#34;terminating connection because of crash of another server process&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;In a moment you should be able to reconnect to the database and repeat your command.&amp;#34;&lt;/span&gt;,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;Debezium Streaming&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;walsender&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:02:43.370 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;repuser&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,164392,&lt;span style="color:#e6db74"&gt;&amp;#34;30.151.40.19:41641&amp;#34;&lt;/span&gt;,66b25869.28228,3,&lt;span style="color:#e6db74"&gt;&amp;#34;streaming 42D3B/1732C5F0&amp;#34;&lt;/span&gt;,2024-08-07 01:07:53 CST,296/0,0,WARNING,57P02,&lt;span style="color:#e6db74"&gt;&amp;#34;terminating connection because of crash of another server process&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;In a moment you should be able to reconnect to the database and repeat your command.&amp;#34;&lt;/span&gt;,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;standby_6666&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;walsender&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:02:43.371 CST,,,447560,,65693cde.6d448,1324,,2023-12-01 09:54:38 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;archiver process (PID 448994) exited with exit code 2&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;postmaster&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:02:43.371 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;logicaluser&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,57755,&lt;span style="color:#e6db74"&gt;&amp;#34;10.33.77.159:38918&amp;#34;&lt;/span&gt;,67125534.e19b,7,&lt;span style="color:#e6db74"&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;,2024-10-18 20:31:48 CST,243/902018192,0,WARNING,57P02,&lt;span style="color:#e6db74"&gt;&amp;#34;terminating connection because of crash of another server process&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;In a moment you should be able to reconnect to the database and repeat your command.&amp;#34;&lt;/span&gt;,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;Debezium Streaming&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;walsender&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:02:43.372 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;logicaluser&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,157915,&lt;span style="color:#e6db74"&gt;&amp;#34;10.33.77.159:43433&amp;#34;&lt;/span&gt;,67408356.268db,7,&lt;span style="color:#e6db74"&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;,2024-11-22 21:12:54 CST,60/3248014863,0,WARNING,57P02,&lt;span style="color:#e6db74"&gt;&amp;#34;terminating connection because of crash of another server process&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;In a moment you should be able to reconnect to the database and repeat your command.&amp;#34;&lt;/span&gt;,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;Debezium Streaming&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;walsender&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--pm停完
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:02:57.534 CST,,,447560,,65693cde.6d448,1325,,2023-12-01 09:54:38 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;database system is shut down&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;postmaster&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:03:49.536 CST,,,211844,,6752bdf3.33b84,1,,2024-12-06 17:03:47 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;ending log output to stderr&amp;#34;&lt;/span&gt;,,&lt;span style="color:#e6db74"&gt;&amp;#34;Future log output will go to log destination &amp;#34;&amp;#34;csvlog&amp;#34;&amp;#34;.&amp;#34;&lt;/span&gt;,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;postmaster&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;17:00:02 postmaster接到fast停库&lt;/p&gt;</description><content:encoded>
&lt;h2 class="relative group"&gt;walsender阻止停库现象
 &lt;div id="walsender阻止停库现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#walsender%e9%98%bb%e6%ad%a2%e5%81%9c%e5%ba%93%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;生产停库日志输出如下：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:00:02.036 CST,,,447560,,65693cde.6d448,1320,,2023-12-01 09:54:38 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;received fast shutdown request&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;postmaster&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:00:02.295 CST,,,447560,,65693cde.6d448,1322,,2023-12-01 09:54:38 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;background worker &amp;#34;&amp;#34;logical replication launcher&amp;#34;&amp;#34; (PID 448996) exited with exit code 1&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;postmaster&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:00:10.627 CST,,,448990,,65693ce0.6d9de,213833,,2023-12-01 09:54:40 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;checkpoint complete: wrote 426844 buffers (5.1%); 0 WAL file(s) added, 0 removed, 5 recycled; write=91.427 s, sync=0.055 s, total=91.508 s; sync files=761, longest=0.028 s, average=0.001 s; distance=2197531 kB, estimate=2680783 kB&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;checkpointer&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:00:10.628 CST,,,448990,,65693ce0.6d9de,213834,,2023-12-01 09:54:40 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;shutting down&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;checkpointer&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--checkpointer做完checkpoint，并处于shutting down状态，pm没有退出
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--160s后pm接收到immediate shutdown，由探活脚本触发
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:02:43.348 CST,,,447560,,65693cde.6d448,1323,,2023-12-01 09:54:38 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;received immediate shutdown request&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;postmaster&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:02:43.370 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;logicaluser&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,283840,&lt;span style="color:#e6db74"&gt;&amp;#34;10.33.77.159:39865&amp;#34;&lt;/span&gt;,6751a2dc.454c0,7,&lt;span style="color:#e6db74"&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;,2024-12-05 20:55:56 CST,89/847309655,0,WARNING,57P02,&lt;span style="color:#e6db74"&gt;&amp;#34;terminating connection because of crash of another server process&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;In a moment you should be able to reconnect to the database and repeat your command.&amp;#34;&lt;/span&gt;,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;Debezium Streaming&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;walsender&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:02:43.370 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;logicaluser&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,157641,&lt;span style="color:#e6db74"&gt;&amp;#34;10.33.77.159:39407&amp;#34;&lt;/span&gt;,67408354.267c9,7,&lt;span style="color:#e6db74"&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;,2024-11-22 21:12:52 CST,9/3193590104,0,WARNING,57P02,&lt;span style="color:#e6db74"&gt;&amp;#34;terminating connection because of crash of another server process&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;In a moment you should be able to reconnect to the database and repeat your command.&amp;#34;&lt;/span&gt;,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;Debezium Streaming&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;walsender&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:02:43.370 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;logicaluser&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,157916,&lt;span style="color:#e6db74"&gt;&amp;#34;10.33.77.159:57038&amp;#34;&lt;/span&gt;,67408356.268dc,7,&lt;span style="color:#e6db74"&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;,2024-11-22 21:12:54 CST,115/3293293502,0,WARNING,57P02,&lt;span style="color:#e6db74"&gt;&amp;#34;terminating connection because of crash of another server process&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;In a moment you should be able to reconnect to the database and repeat your command.&amp;#34;&lt;/span&gt;,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;Debezium Streaming&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;walsender&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:02:43.370 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;repuser&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,164392,&lt;span style="color:#e6db74"&gt;&amp;#34;30.151.40.19:41641&amp;#34;&lt;/span&gt;,66b25869.28228,3,&lt;span style="color:#e6db74"&gt;&amp;#34;streaming 42D3B/1732C5F0&amp;#34;&lt;/span&gt;,2024-08-07 01:07:53 CST,296/0,0,WARNING,57P02,&lt;span style="color:#e6db74"&gt;&amp;#34;terminating connection because of crash of another server process&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;In a moment you should be able to reconnect to the database and repeat your command.&amp;#34;&lt;/span&gt;,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;standby_6666&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;walsender&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:02:43.371 CST,,,447560,,65693cde.6d448,1324,,2023-12-01 09:54:38 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;archiver process (PID 448994) exited with exit code 2&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;postmaster&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:02:43.371 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;logicaluser&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,57755,&lt;span style="color:#e6db74"&gt;&amp;#34;10.33.77.159:38918&amp;#34;&lt;/span&gt;,67125534.e19b,7,&lt;span style="color:#e6db74"&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;,2024-10-18 20:31:48 CST,243/902018192,0,WARNING,57P02,&lt;span style="color:#e6db74"&gt;&amp;#34;terminating connection because of crash of another server process&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;In a moment you should be able to reconnect to the database and repeat your command.&amp;#34;&lt;/span&gt;,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;Debezium Streaming&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;walsender&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:02:43.372 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;logicaluser&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,157915,&lt;span style="color:#e6db74"&gt;&amp;#34;10.33.77.159:43433&amp;#34;&lt;/span&gt;,67408356.268db,7,&lt;span style="color:#e6db74"&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;,2024-11-22 21:12:54 CST,60/3248014863,0,WARNING,57P02,&lt;span style="color:#e6db74"&gt;&amp;#34;terminating connection because of crash of another server process&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;In a moment you should be able to reconnect to the database and repeat your command.&amp;#34;&lt;/span&gt;,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;Debezium Streaming&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;walsender&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--pm停完
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:02:57.534 CST,,,447560,,65693cde.6d448,1325,,2023-12-01 09:54:38 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;database system is shut down&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;postmaster&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-12-06 17:03:49.536 CST,,,211844,,6752bdf3.33b84,1,,2024-12-06 17:03:47 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;ending log output to stderr&amp;#34;&lt;/span&gt;,,&lt;span style="color:#e6db74"&gt;&amp;#34;Future log output will go to log destination &amp;#34;&amp;#34;csvlog&amp;#34;&amp;#34;.&amp;#34;&lt;/span&gt;,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;postmaster&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;17:00:02 postmaster接到fast停库&lt;/p&gt;
&lt;p&gt;17:00:10 checkpoint做完，checkpointer停了&lt;/p&gt;
&lt;p&gt;17:02:43 postmaster接到immediate停库&lt;/p&gt;
&lt;p&gt;17:02:43 1个物理链路和5个逻辑链路walsender停了&lt;/p&gt;
&lt;p&gt;17:02:57 postmaster停了&lt;/p&gt;
&lt;p&gt;17:03:49 postmaster接到启动任务&lt;/p&gt;
&lt;p&gt;从以上信息可以看出，实际上还是walsender阻止了停库&lt;/p&gt;

&lt;h2 class="relative group"&gt;停库和信号
 &lt;div id="停库和信号" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%81%9c%e5%ba%93%e5%92%8c%e4%bf%a1%e5%8f%b7" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;在撸源码前需要先了解信号和pg中的信号注册&lt;/p&gt;

&lt;h3 class="relative group"&gt;pg中的常用信号
 &lt;div id="pg中的常用信号" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#pg%e4%b8%ad%e7%9a%84%e5%b8%b8%e7%94%a8%e4%bf%a1%e5%8f%b7" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;操作系统信号：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ kill -l
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1&lt;span style="color:#f92672"&gt;)&lt;/span&gt; SIGHUP 2&lt;span style="color:#f92672"&gt;)&lt;/span&gt; SIGINT 3&lt;span style="color:#f92672"&gt;)&lt;/span&gt; SIGQUIT 4&lt;span style="color:#f92672"&gt;)&lt;/span&gt; SIGILL 5&lt;span style="color:#f92672"&gt;)&lt;/span&gt; SIGTRAP
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 6&lt;span style="color:#f92672"&gt;)&lt;/span&gt; SIGABRT 7&lt;span style="color:#f92672"&gt;)&lt;/span&gt; SIGBUS 8&lt;span style="color:#f92672"&gt;)&lt;/span&gt; SIGFPE 9&lt;span style="color:#f92672"&gt;)&lt;/span&gt; SIGKILL 10&lt;span style="color:#f92672"&gt;)&lt;/span&gt; SIGUSR1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;11&lt;span style="color:#f92672"&gt;)&lt;/span&gt; SIGSEGV 12&lt;span style="color:#f92672"&gt;)&lt;/span&gt; SIGUSR2 13&lt;span style="color:#f92672"&gt;)&lt;/span&gt; SIGPIPE 14&lt;span style="color:#f92672"&gt;)&lt;/span&gt; SIGALRM 15&lt;span style="color:#f92672"&gt;)&lt;/span&gt; SIGTERM
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;16&lt;span style="color:#f92672"&gt;)&lt;/span&gt; SIGSTKFLT 17&lt;span style="color:#f92672"&gt;)&lt;/span&gt; SIGCHLD 18&lt;span style="color:#f92672"&gt;)&lt;/span&gt; SIGCONT 19&lt;span style="color:#f92672"&gt;)&lt;/span&gt; SIGSTOP 20&lt;span style="color:#f92672"&gt;)&lt;/span&gt; SIGTSTP
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;PG常用的信号：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-1&lt;/code&gt; 或&lt;code&gt;-SIGHUP&lt;/code&gt;：挂起信号，在PG中通常是通知进程重新加载配置。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-2&lt;/code&gt; 或&lt;code&gt;-SIGINT&lt;/code&gt;：中断信号（通常是&lt;code&gt;Ctrl+C&lt;/code&gt;），在pg中同城对应取消命令。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-3&lt;/code&gt;或&lt;code&gt;-SIGQUIT&lt;/code&gt;：pg中通常是强制退出die&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-9&lt;/code&gt; 或 &lt;code&gt;-SIGKILL&lt;/code&gt;：无条件终止信号。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-15&lt;/code&gt;或 &lt;code&gt;-SIGTERM&lt;/code&gt;：终止信号，&lt;code&gt;pg_terminate_backend&lt;/code&gt;使用的信号，pg中通常是合理退出&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-10&lt;/code&gt;或&lt;code&gt;-SIGUSR1&lt;/code&gt;：自定义信号&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-12&lt;/code&gt;或&lt;code&gt;-SIGUSR2&lt;/code&gt;：自定义信号&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-17&lt;/code&gt;或&lt;code&gt;SIGCHLD&lt;/code&gt;：pm进程使用的信号，一般是子进程退出后pm接受该信号触发回收子进程任务&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;PG中具体哪种类型的进程注册的信号含义，看各自进程源码基本都能找到。&lt;/p&gt;

&lt;h3 class="relative group"&gt;pg_ctl 定义的停库
 &lt;div id="pg_ctl-定义的停库" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#pg_ctl-%e5%ae%9a%e4%b9%89%e7%9a%84%e5%81%9c%e5%ba%93" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;有几种方法可以关闭pg库。在底层，它们都归结为向postmaster进程发送一个信号。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;signal&lt;/th&gt;
 &lt;th&gt;pg_ctl&lt;/th&gt;
 &lt;th&gt;含义&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;SIGTERM&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;em&gt;Smart Shutdown&lt;/em&gt;&lt;/td&gt;
 &lt;td&gt;不允许新的连接，但允许现有会话正常结束其工作。只有在所有会话终止后，它才会关闭&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;SIGINT&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;em&gt;Fast Shutdown&lt;/em&gt;&lt;/td&gt;
 &lt;td&gt;服务器不允许新的连接，并向所有现有的子进程发送&lt;strong&gt;SIGTERM&lt;/strong&gt;，中止当前的事务并迅速退出。等待几乎所有子进程（有几个子进程不需要）退出，最后关闭&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;SIGQUIT&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;em&gt;Immediate Shutdown&lt;/em&gt;&lt;/td&gt;
 &lt;td&gt;将向所有子进程发送&lt;strong&gt;SIGQUIT&lt;/strong&gt;，并等待它们终止。如果在5秒内有子进程没有终止，它们将被发送&lt;strong&gt;SIGKILL&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;注意，&lt;code&gt;pg_ctl&lt;/code&gt;没有发送&lt;code&gt;SIGKILL&lt;/code&gt;（&lt;code&gt;kill -9&lt;/code&gt;）的参数，但其实是可以直接对pm发送&lt;code&gt;SIGKILL&lt;/code&gt;的，但肯定不推荐这么做，&lt;code&gt;SIGKILL&lt;/code&gt; pm时pm不会对子进程、共享内存、信号量做任何处理。因为&lt;code&gt;SIGQUIT&lt;/code&gt; pm有兜底逻辑做子进程的&lt;code&gt;SIGKILL&lt;/code&gt;，所以&lt;code&gt;SIGQUIT&lt;/code&gt; pm基本能保证pm能停下来。&lt;/p&gt;
&lt;p&gt;在源码中，&lt;strong&gt;停库状态&lt;/strong&gt;总共只有3种，跟停库方式相对应：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/* Startup/shutdown state */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define			NoShutdown		0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define			SmartShutdown	1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define			FastShutdown	2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define			ImmediateShutdown	3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这些状态会在停库routine源码中常见，一般通过变量&lt;code&gt;Shutdown&lt;/code&gt;来判断当前停库状态，如：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Shutdown &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; FastShutdown&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 class="relative group"&gt;pm信号
 &lt;div id="pm信号" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#pm%e4%bf%a1%e5%8f%b7" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;当pm收到对应信号时做相应的处理：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;PostmasterMain&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; argc, &lt;span style="color:#66d9ef"&gt;char&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;argv[])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal_pm&lt;/span&gt;(SIGHUP, SIGHUP_handler);	&lt;span style="color:#75715e"&gt;/* reread config file and have
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;											 * children do same */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal_pm&lt;/span&gt;(SIGINT, pmdie); &lt;span style="color:#75715e"&gt;/* send SIGTERM and shut down */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal_pm&lt;/span&gt;(SIGQUIT, pmdie);	&lt;span style="color:#75715e"&gt;/* send SIGQUIT and die */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal_pm&lt;/span&gt;(SIGTERM, pmdie);	&lt;span style="color:#75715e"&gt;/* wait for children and shut down */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal_pm&lt;/span&gt;(SIGALRM, SIG_IGN);	&lt;span style="color:#75715e"&gt;/* ignored */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal_pm&lt;/span&gt;(SIGPIPE, SIG_IGN);	&lt;span style="color:#75715e"&gt;/* ignored */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal_pm&lt;/span&gt;(SIGUSR1, sigusr1_handler);	&lt;span style="color:#75715e"&gt;/* message from child process */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal_pm&lt;/span&gt;(SIGUSR2, dummy_handler);	&lt;span style="color:#75715e"&gt;/* unused, reserve for children */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal_pm&lt;/span&gt;(SIGCHLD, reaper);	&lt;span style="color:#75715e"&gt;/* handle child termination */&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pmdie&lt;/code&gt;：停库的三种信号会调用&lt;code&gt;pmdie&lt;/code&gt;函数，&lt;code&gt;pmdie&lt;/code&gt;是停库的关键函数，下面会重点分析。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;reaper&lt;/code&gt;：停库时会处理子进程退出清理，所以在停库的逻辑中。子进程退出会给pm发生&lt;code&gt;SIGCHLD&lt;/code&gt;信号，然后进入&lt;code&gt;reaper&lt;/code&gt;清理子进程，每种子进程的清理也有自己的逻辑，比如checkpointer进程的正常退出会判断archiver和walsender是否完成了各自的任务。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sigusr1&lt;/code&gt;、&lt;code&gt;sigusr2&lt;/code&gt;：&lt;code&gt;sigusr1_handler&lt;/code&gt;是&lt;code&gt;SIGUSER1&lt;/code&gt;的标准routine，每种子进程对于&lt;code&gt;SIGUSR1&lt;/code&gt;的处理行为各不同；&lt;code&gt;SIGUSR2&lt;/code&gt;完全是子进程自定义行为了，有些子进程没有注册这个信号。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;walsender的信号
 &lt;div id="walsender的信号" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#walsender%e7%9a%84%e4%bf%a1%e5%8f%b7" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;子进程fork出来时，首先就要注册信号。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;WalSndSignals&lt;/code&gt;注册walsender进程的信号：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/* Set up signal handlers */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;WalSndSignals&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/* Set up signal handlers */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal&lt;/span&gt;(SIGHUP, SignalHandlerForConfigReload);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal&lt;/span&gt;(SIGINT, StatementCancelHandler);	&lt;span style="color:#75715e"&gt;/* query cancel */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal&lt;/span&gt;(SIGTERM, die);		&lt;span style="color:#75715e"&gt;/* request shutdown */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal&lt;/span&gt;(SIGQUIT, quickdie);	&lt;span style="color:#75715e"&gt;/* hard crash time */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;InitializeTimeouts&lt;/span&gt;();		&lt;span style="color:#75715e"&gt;/* establishes SIGALRM handler */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal&lt;/span&gt;(SIGPIPE, SIG_IGN);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal&lt;/span&gt;(SIGUSR1, procsignal_sigusr1_handler);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal&lt;/span&gt;(SIGUSR2, WalSndLastCycleHandler);	&lt;span style="color:#75715e"&gt;/* request a last cycle and
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;												 * shutdown */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;要注意&lt;code&gt;SIGUSR1&lt;/code&gt;和&lt;code&gt;SIGUSR2&lt;/code&gt;&lt;/p&gt;

&lt;h3 class="relative group"&gt;checkpointer的信号
 &lt;div id="checkpointer的信号" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#checkpointer%e7%9a%84%e4%bf%a1%e5%8f%b7" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;CheckpointerMain&lt;/code&gt;注册checkpointer的信号：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;CheckpointerMain&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//checkpointer会屏蔽SIGTERM，真正的停止是SIGUSR2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal&lt;/span&gt;(SIGHUP, SignalHandlerForConfigReload);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal&lt;/span&gt;(SIGINT, ReqCheckpointHandler); &lt;span style="color:#75715e"&gt;/* request checkpoint */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal&lt;/span&gt;(SIGTERM, SIG_IGN); &lt;span style="color:#75715e"&gt;/* ignore SIGTERM */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal&lt;/span&gt;(SIGQUIT, SignalHandlerForCrashExit);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal&lt;/span&gt;(SIGALRM, SIG_IGN);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal&lt;/span&gt;(SIGPIPE, SIG_IGN);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal&lt;/span&gt;(SIGUSR1, procsignal_sigusr1_handler);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal&lt;/span&gt;(SIGUSR2, SignalHandlerForShutdownRequest);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;要注意&lt;code&gt;SIGUSR1&lt;/code&gt;和&lt;code&gt;SIGUSR2&lt;/code&gt;，同时要注意checkpointer是没有注册&lt;code&gt;SIGTERM&lt;/code&gt;的&lt;/p&gt;

&lt;h2 class="relative group"&gt;停库源码分析
 &lt;div id="停库源码分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%81%9c%e5%ba%93%e6%ba%90%e7%a0%81%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;pm信号处理和状态机
 &lt;div id="pm信号处理和状态机" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#pm%e4%bf%a1%e5%8f%b7%e5%a4%84%e7%90%86%e5%92%8c%e7%8a%b6%e6%80%81%e6%9c%ba" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;pmdie&lt;/code&gt;函数用于处理不同的postmaster signals，包括子进程给pm发送的&lt;code&gt;SIGCHILD&lt;/code&gt;和&lt;code&gt;pg_ctl&lt;/code&gt;发送的停库信号。pm信号处理主体逻辑是根据signal转换&lt;code&gt;pmState&lt;/code&gt;状态机状态，并进入状态机&lt;code&gt;PostmasterStateMachine&lt;/code&gt;处理。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pmdie&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * pmdie -- signal handler for processing various postmaster signals.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;pmdie&lt;/span&gt;(SIGNAL_ARGS)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;			save_errno &lt;span style="color:#f92672"&gt;=&lt;/span&gt; errno;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; (postgres_signal_arg)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; SIGTERM:&lt;span style="color:#75715e"&gt;//Smart Shutdown
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (pmState &lt;span style="color:#f92672"&gt;==&lt;/span&gt; PM_RUN)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				connsAllowed &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ALLOW_SUPERUSER_CONNS;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//smart shutdown没有处理pmstate，直接交给状态机处理
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;//此时正常情况pmState = PM_RUN
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;PostmasterStateMachine&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; SIGINT:&lt;span style="color:#75715e"&gt;//Fast Shutdown
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (pmState &lt;span style="color:#f92672"&gt;==&lt;/span&gt; PM_RUN &lt;span style="color:#f92672"&gt;||&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					 pmState &lt;span style="color:#f92672"&gt;==&lt;/span&gt; PM_HOT_STANDBY)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#75715e"&gt;/* Report that we&amp;#39;re about to zap live client sessions */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;ereport&lt;/span&gt;(LOG,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						(&lt;span style="color:#a6e22e"&gt;errmsg&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;aborting any active transactions&amp;#34;&lt;/span&gt;)));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				pmState &lt;span style="color:#f92672"&gt;=&lt;/span&gt; PM_STOP_BACKENDS;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;//Fast Shutdown将pmstate转换为PM_STOP_BACKENDS
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//然后交给状态机处理
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;PostmasterStateMachine&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; SIGQUIT:&lt;span style="color:#75715e"&gt;//Immediate Shutdown
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;TerminateChildren&lt;/span&gt;(SIGQUIT);&lt;span style="color:#75715e"&gt;//abort all children with SIGQUIT, wait for them to exit
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			pmState &lt;span style="color:#f92672"&gt;=&lt;/span&gt; PM_WAIT_BACKENDS;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/* set stopwatch for them to die */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			AbortStartTime &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;(NULL);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//Immediate Shutdown将pmstate转换为PM_WAIT_BACKENDS
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//进入状态机前处理也会children
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//先用SIGQUIT中断children，等待他们退出
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//然后用SIGKILL处理还在的children
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//最后非一致性退出
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;PostmasterStateMachine&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;在进入状态机处理函数前先看下postmaster的状态有哪些：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;typedef&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;enum&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	PM_INIT,					&lt;span style="color:#75715e"&gt;/* postmaster starting */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	PM_STARTUP,					&lt;span style="color:#75715e"&gt;/* waiting for startup subprocess */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	PM_RECOVERY,				&lt;span style="color:#75715e"&gt;/* in archive recovery mode */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	PM_HOT_STANDBY,				&lt;span style="color:#75715e"&gt;/* in hot standby mode */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	PM_RUN,						&lt;span style="color:#75715e"&gt;/* normal &amp;#34;database is alive&amp;#34; state */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	PM_STOP_BACKENDS,			&lt;span style="color:#75715e"&gt;/* need to stop remaining backends */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	PM_WAIT_BACKENDS,			&lt;span style="color:#75715e"&gt;/* waiting for live backends to exit */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	PM_SHUTDOWN,				&lt;span style="color:#75715e"&gt;/* waiting for checkpointer to do shutdown
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;								 * ckpt */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	PM_SHUTDOWN_2,				&lt;span style="color:#75715e"&gt;/* waiting for archiver and walsenders to
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;								 * finish */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	PM_WAIT_DEAD_END,			&lt;span style="color:#75715e"&gt;/* waiting for dead_end children to exit */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	PM_NO_CHILDREN				&lt;span style="color:#75715e"&gt;/* all important children have exited */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} PMState;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;由于正常都是running态关库，这里只需要关注&lt;code&gt;PM_RUN&lt;/code&gt;以下的状态即可。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;PostmasterStateMachine&lt;/code&gt;的执行函数实际上有顺序逻辑：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Advance the postmaster&amp;#39;s state machine and take actions as appropriate
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * This is common code for pmdie(), reaper() and sigusr1_handler(), which
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * receive the signals that might mean we need to change state.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;PostmasterStateMachine&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;//smart shutdown，此时的pmState应是PM_RUN
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (pmState &lt;span style="color:#f92672"&gt;==&lt;/span&gt; PM_RUN &lt;span style="color:#f92672"&gt;||&lt;/span&gt; pmState &lt;span style="color:#f92672"&gt;==&lt;/span&gt; PM_HOT_STANDBY)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (connsAllowed &lt;span style="color:#f92672"&gt;==&lt;/span&gt; ALLOW_NO_CONNS)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//当所有normal backend都退出后，pmState转换PM_STOP_BACKENDS
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;CountChildren&lt;/span&gt;(BACKEND_TYPE_NORMAL) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				pmState &lt;span style="color:#f92672"&gt;=&lt;/span&gt; PM_STOP_BACKENDS;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//PM_STOP_BACKENDS会中止一些比较核心的子进程，有些子进程会继续运行
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//autovacuum，bgwriter，walwriter，startup，walreiver会停止
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//walsender，checkpointer, archiver, stats, and syslogger会继续跑
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//smart shutdown后段会进入此逻辑，fast shutdown直接进入此逻辑
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (pmState &lt;span style="color:#f92672"&gt;==&lt;/span&gt; PM_STOP_BACKENDS)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		...		
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;//注意walsender这句话！
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* Signal all backend children except walsenders */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;SignalSomeChildren&lt;/span&gt;(SIGTERM,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						 BACKEND_TYPE_ALL &lt;span style="color:#f92672"&gt;-&lt;/span&gt; BACKEND_TYPE_WALSND);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* and the autovac launcher too */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (AutoVacPID &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;signal_child&lt;/span&gt;(AutoVacPID, SIGTERM);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* and the bgwriter too */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (BgWriterPID &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;signal_child&lt;/span&gt;(BgWriterPID, SIGTERM);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* and the walwriter too */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (WalWriterPID &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;signal_child&lt;/span&gt;(WalWriterPID, SIGTERM);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* If we&amp;#39;re in recovery, also stop startup and walreceiver procs */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (StartupPID &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;signal_child&lt;/span&gt;(StartupPID, SIGTERM);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (WalReceiverPID &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;signal_child&lt;/span&gt;(WalReceiverPID, SIGTERM);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* checkpointer, archiver, stats, and syslogger may continue for now */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//将pmState从PM_STOP_BACKENDS转换为PM_WAIT_BACKEND
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//PM_WAIT_BACKEND表示等待backend退出
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		pmState &lt;span style="color:#f92672"&gt;=&lt;/span&gt; PM_WAIT_BACKENDS;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * If we are in a state-machine state that implies waiting for backends to
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * exit, see if they&amp;#39;re all gone, and change state if so.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//smart shutdown,fast shutdown后段会进入此逻辑
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//immediate shutdown进入状态机处理时，直接进入此逻辑
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (pmState &lt;span style="color:#f92672"&gt;==&lt;/span&gt; PM_WAIT_BACKENDS)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//crash recovery和immediate shutdown时，checkpointer需要妥善退出
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//archiver, stats, and syslogger不需要处理，因为他们没有连到shared memory
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//Walsenders也不需要处理，它将在checkpoint记录写入之后退出，就像archiver进程一样
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;CountChildren&lt;/span&gt;(BACKEND_TYPE_ALL &lt;span style="color:#f92672"&gt;-&lt;/span&gt; BACKEND_TYPE_WALSND) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			StartupPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			WalReceiverPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			BgWriterPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			(CheckpointerPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			 (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;FatalError &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; Shutdown &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; ImmediateShutdown)) &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			WalWriterPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			AutoVacPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (Shutdown &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; ImmediateShutdown &lt;span style="color:#f92672"&gt;||&lt;/span&gt; FatalError)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#75715e"&gt;//ImmediateShutdown会等待dead end进程结束
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				pmState &lt;span style="color:#f92672"&gt;=&lt;/span&gt; PM_WAIT_DEAD_END;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 * We already SIGQUIT&amp;#39;d the archiver and stats processes, if
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 * any, when we started immediate shutdown or entered
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 * FatalError state.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//smart，fast shutdown走此逻辑
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//常规子进程都退出了，此时该通知checkpointer做shutdown checkpoint
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;Assert&lt;/span&gt;(Shutdown &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; NoShutdown);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#75715e"&gt;//如果checkpointer进程没有，就启动
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (CheckpointerPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					CheckpointerPID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;StartCheckpointer&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#75715e"&gt;/* And tell it to shut down */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (CheckpointerPID &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//向Checkpointer发送SIGUSR2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//pmState = PM_SHUTDOWN
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					&lt;span style="color:#a6e22e"&gt;signal_child&lt;/span&gt;(CheckpointerPID, SIGUSR2);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					pmState &lt;span style="color:#f92672"&gt;=&lt;/span&gt; PM_SHUTDOWN;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//没有启动起来Checkpointer是一个比较严重的问题
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					FatalError &lt;span style="color:#f92672"&gt;=&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					pmState &lt;span style="color:#f92672"&gt;=&lt;/span&gt; PM_WAIT_DEAD_END;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					&lt;span style="color:#75715e"&gt;/* Kill the walsenders, archiver and stats collector too */&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//注释说kill walsender，实际上根本没有；至少不是SIGQUIT去停的
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					&lt;span style="color:#a6e22e"&gt;SignalChildren&lt;/span&gt;(SIGQUIT);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (PgArchPID &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						&lt;span style="color:#a6e22e"&gt;signal_child&lt;/span&gt;(PgArchPID, SIGQUIT);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (PgStatPID &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						&lt;span style="color:#a6e22e"&gt;signal_child&lt;/span&gt;(PgStatPID, SIGQUIT);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//pmdie函数和状态机函数不会制造PM_SHUTDOWN_2这个状态，但是reaper会
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//reaper在处理checkpointer的退出时，会设置pmState = PM_SHUTDOWN_2；当然在reaper函数最后会进入状态机函数，也就是这里
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (pmState &lt;span style="color:#f92672"&gt;==&lt;/span&gt; PM_SHUTDOWN_2)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * PM_SHUTDOWN_2 state ends when there&amp;#39;s no other children than
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * dead_end children left. There shouldn&amp;#39;t be any regular backends
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * left by now anyway; what we&amp;#39;re really waiting for is walsenders and
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * archiver.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//PM_SHUTDOWN_2本质上是等待walsender和archiver
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//只是更改了pmState状态
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (PgArchPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;CountChildren&lt;/span&gt;(BACKEND_TYPE_ALL) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			pmState &lt;span style="color:#f92672"&gt;=&lt;/span&gt; PM_WAIT_DEAD_END;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (pmState &lt;span style="color:#f92672"&gt;==&lt;/span&gt; PM_WAIT_DEAD_END)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//PM_WAIT_DEAD_END表示BackendList已经完全清空
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;dlist_is_empty&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;BackendList) &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			PgArchPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; PgStatPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/* These other guys should be dead already */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;Assert&lt;/span&gt;(StartupPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;Assert&lt;/span&gt;(WalReceiverPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;Assert&lt;/span&gt;(BgWriterPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;Assert&lt;/span&gt;(CheckpointerPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;Assert&lt;/span&gt;(WalWriterPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;Assert&lt;/span&gt;(AutoVacPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/* syslogger is not considered here */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			pmState &lt;span style="color:#f92672"&gt;=&lt;/span&gt; PM_NO_CHILDREN;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//PM_NO_CHILDREN是停库的最后一个状态，表示可以正常停库了
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (Shutdown &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; NoShutdown &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pmState &lt;span style="color:#f92672"&gt;==&lt;/span&gt; PM_NO_CHILDREN)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (FatalError)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;ereport&lt;/span&gt;(LOG, (&lt;span style="color:#a6e22e"&gt;errmsg&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;abnormal database system shutdown&amp;#34;&lt;/span&gt;)));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//异常退出pm
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;ExitPostmaster&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		 	&lt;span style="color:#75715e"&gt;//正常退出pm
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;ExitPostmaster&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;reaper&lt;/code&gt;是进程回收函数，子进程退出后会发送pm &lt;code&gt;SIGCHLD&lt;/code&gt;信号，pm通过&lt;code&gt;reaper&lt;/code&gt;函数清理进程。 如backend、startup、checkpointer等进程都有自己的清理流程。&lt;/p&gt;
&lt;p&gt;这里只看checkpointer的清理，另外&lt;code&gt;reaper&lt;/code&gt;中没有关于walsender的清理逻辑：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (pid &lt;span style="color:#f92672"&gt;==&lt;/span&gt; CheckpointerPID)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			CheckpointerPID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//Checkpointer进程是正常退出，且pmState为PM_SHUTDOWN:等待checkpoint完成态
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;EXIT_STATUS_0&lt;/span&gt;(exitstatus) &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pmState &lt;span style="color:#f92672"&gt;==&lt;/span&gt; PM_SHUTDOWN)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 * OK, we saw normal exit of the checkpointer after it&amp;#39;s been
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 * told to shut down. We expect that it wrote a shutdown
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 * checkpoint. (If for some reason it didn&amp;#39;t, recovery will
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 * occur on next postmaster start.)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 * At this point we should have no normal backend children
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 * left (else we&amp;#39;d not be in PM_SHUTDOWN state) but we might
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 * have dead_end children to wait for.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 * If we have an archiver subprocess, tell it to do a last
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 * archive cycle and quit. Likewise, if we have walsender
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 * processes, tell them to send any remaining WAL and quit.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;Assert&lt;/span&gt;(Shutdown &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; NoShutdown);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#75715e"&gt;//最后一次唤醒pgarch
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (PgArchPID &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					&lt;span style="color:#a6e22e"&gt;signal_child&lt;/span&gt;(PgArchPID, SIGUSR2); &lt;span style="color:#75715e"&gt;//pgarch SIGUSR2=pgarch_waken_stop
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//最后一次唤醒walsender
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;SignalChildren&lt;/span&gt;(SIGUSR2);&lt;span style="color:#75715e"&gt;//walsender SIGUSR2=WalSndLastCycleHandler
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//这里设置了PM_SHUTDOWN_2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//此时Checkpointer正常退出完成了，这里应该等pgarch和walsender最后一个任务完成
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//即PM_SHUTDOWN_2态
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pmState &lt;span style="color:#f92672"&gt;=&lt;/span&gt; PM_SHUTDOWN_2;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//checkpointer进程异常退出都认为是crash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;HandleChildCrash&lt;/span&gt;(pid, exitstatus,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;								 &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;checkpointer process&amp;#34;&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;continue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;//最后reaper还是会进入状态机函数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;PostmasterStateMachine&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 class="relative group"&gt;checkpointer和walsender进程的退出
 &lt;div id="checkpointer和walsender进程的退出" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#checkpointer%e5%92%8cwalsender%e8%bf%9b%e7%a8%8b%e7%9a%84%e9%80%80%e5%87%ba" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;checkpointer主循环处理请求和关闭进程：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;CheckpointerMain&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * Loop forever
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (;;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt;		do_checkpoint &lt;span style="color:#f92672"&gt;=&lt;/span&gt; false;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;			flags &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;pg_time_t&lt;/span&gt;	now;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;			elapsed_secs;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;			cur_timeout;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* Clear any already-pending wakeups */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;ResetLatch&lt;/span&gt;(MyLatch);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * Process any requests or signals received recently.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//处理近期的同步请求和信号
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;AbsorbSyncRequests&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;HandleCheckpointerInterrupts&lt;/span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;checkpointer关闭函数：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Process any new interrupts.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;HandleCheckpointerInterrupts&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (ShutdownRequestPending)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * From here on, elog(ERROR) should end with exit(1), not send control
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * back to the sigsetjmp block above
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		ExitOnAnyError &lt;span style="color:#f92672"&gt;=&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;ShutdownXLOG&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);&lt;span style="color:#75715e"&gt;//这里会写shutdown checkpoint 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;proc_exit&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);&lt;span style="color:#75715e"&gt;//正常退出态为0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;checkpointer的退出需要等待&lt;code&gt;ShutdownXLOG&lt;/code&gt;完成。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ShutdownXLOG&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * This must be called ONCE during postmaster or standalone-backend shutdown
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;ShutdownXLOG&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; code, Datum arg)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;//这里有个checkpointer的shutting down的日志，这个日志一般都会看到
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;ereport&lt;/span&gt;(IsPostmasterEnvironment &lt;span style="color:#f92672"&gt;?&lt;/span&gt; LOG : NOTICE,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			(&lt;span style="color:#a6e22e"&gt;errmsg&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;shutting down&amp;#34;&lt;/span&gt;)));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * Signal walsenders to move to stopping state.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//walsender初始化stopping
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;WalSndInitStopping&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//等待所有walsender处于stopping状态
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;WalSndWaitStopping&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;RecoveryInProgress&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;CreateRestartPoint&lt;/span&gt;(CHECKPOINT_IS_SHUTDOWN &lt;span style="color:#f92672"&gt;|&lt;/span&gt; CHECKPOINT_IMMEDIATE);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * If archiving is enabled, rotate the last XLOG file so that all the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * remaining records are archived (postmaster wakes up the archiver
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * process one more time at the end of shutdown). The checkpoint
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * record will go to the next XLOG file and won&amp;#39;t be archived (yet).
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;XLogArchivingActive&lt;/span&gt;() &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;XLogArchiveCommandSet&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;RequestXLogSwitch&lt;/span&gt;(false);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;//这里就是shutdown checkpoint的创建函数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;CreateCheckPoint&lt;/span&gt;(CHECKPOINT_IS_SHUTDOWN &lt;span style="color:#f92672"&gt;|&lt;/span&gt; CHECKPOINT_IMMEDIATE);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;ShutdownCLOG&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;ShutdownCommitTs&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;ShutdownSUBTRANS&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;ShutdownMultiXact&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;checkpointer通知所有walsender开始stopping：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Signal all walsenders to move to stopping state.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * This will trigger walsenders to move to a state where no further WAL can be
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * generated. See this file&amp;#39;s header for details.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;WalSndInitStopping&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;			i;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (i &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; i &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; max_wal_senders; i&lt;span style="color:#f92672"&gt;++&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		WalSnd	 &lt;span style="color:#f92672"&gt;*&lt;/span&gt;walsnd &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;WalSndCtl&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;walsnds[i];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;pid_t&lt;/span&gt;		pid;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;SpinLockAcquire&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;walsnd&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;mutex);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		pid &lt;span style="color:#f92672"&gt;=&lt;/span&gt; walsnd&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;pid;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;SpinLockRelease&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;walsnd&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;mutex);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (pid &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;continue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;SendProcSignal&lt;/span&gt;(pid, PROCSIG_WALSND_INIT_STOPPING, InvalidBackendId);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;walsender通过&lt;code&gt;SendProcSignal&lt;/code&gt;函数收到信号，信号为&lt;code&gt;SIGUSR1&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * SendProcSignal
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *		Send a signal to a Postgres process
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Providing backendId is optional, but it will speed up the operation.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * On success (a signal was sent), zero is returned.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * On error, -1 is returned, and errno is set (typically to ESRCH or EPERM).
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Not to be confused with ProcSendSignal
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;SendProcSignal&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;pid_t&lt;/span&gt; pid, ProcSignalReason reason, BackendId backendId)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * BackendId not provided, so search the array using pid. We search
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * the array back to front so as to reduce search overhead. Passing
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * InvalidBackendId means that the target is most likely an auxiliary
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * process, which will have a slot near the end of the array.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;			i;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (i &lt;span style="color:#f92672"&gt;=&lt;/span&gt; NumProcSignalSlots &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;; i &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; i&lt;span style="color:#f92672"&gt;--&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			slot &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;ProcSignal&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;psh_slot[i];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (slot&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;pss_pid &lt;span style="color:#f92672"&gt;==&lt;/span&gt; pid)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#75715e"&gt;/* the above note about race conditions applies here too */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#75715e"&gt;/* Atomically set the proper flag */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				slot&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;pss_signalFlags[reason] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#75715e"&gt;/* Send signal */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;kill&lt;/span&gt;(pid, SIGUSR1);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	errno &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ESRCH;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;walsender中&lt;code&gt;SIGUSR1&lt;/code&gt;的注册为如下：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal&lt;/span&gt;(SIGUSR1, procsignal_sigusr1_handler);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;pqsignal&lt;/span&gt;(SIGUSR2, WalSndLastCycleHandler);	&lt;span style="color:#75715e"&gt;/* request a last cycle and
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;												 * shutdown */&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;sigusr1根据信号的reason来分类处理&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * procsignal_sigusr1_handler - handle SIGUSR1 signal.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;procsignal_sigusr1_handler&lt;/span&gt;(SIGNAL_ARGS)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;CheckProcSignal&lt;/span&gt;(PROCSIG_WALSND_INIT_STOPPING))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;HandleWalSndInitStopping&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;处理&lt;code&gt;PROCSIG_WALSND_INIT_STOPPING&lt;/code&gt;的函数为&lt;code&gt;HandleWalSndInitStopping&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Handle PROCSIG_WALSND_INIT_STOPPING signal.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;HandleWalSndInitStopping&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;Assert&lt;/span&gt;(am_walsender);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * If replication has not yet started, die like with SIGTERM. If
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * replication is active, only set a flag and wake up the main loop. It
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * will send any outstanding WAL, wait for it to be replicated to the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * standby, and then exit gracefully.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;replication_active)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;kill&lt;/span&gt;(MyProcPid, SIGTERM);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		got_STOPPING &lt;span style="color:#f92672"&gt;=&lt;/span&gt; true;&lt;span style="color:#75715e"&gt;//如果walsender是active的，initstopping函数只会设置状态，让主循环去处理
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这个注释中的main loop有点意义不明，walsender有主循环&lt;code&gt;ServerLoop&lt;/code&gt;，但实际上只有&lt;code&gt;WalSndWaitForWal&lt;/code&gt;中的循环才有关于&lt;code&gt;got_STOPPING&lt;/code&gt;的判断。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;WalSndWaitForWal&lt;/code&gt;函数是walsender等待新的wal日志的主循环函数。由于wal record生成之初还在内存中，walwriter会根据一定的条件flush，不是随时都flush。&lt;code&gt;WalSndWaitForWal&lt;/code&gt;函数通过对比当前sent的LSN和flushed的LSN，以判断是否需要send新的wal日志。换句话说，没有flush的wal不会传递，flush过的wal才会传给下游。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;WalSndWaitForWal&lt;/code&gt;关于stopping的代码段：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Wait till WAL &amp;lt; loc is flushed to disk so it can be safely sent to client.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Returns end LSN of flushed WAL. Normally this will be &amp;gt;= loc, but
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * if we detect a shutdown request (either from postmaster or client)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * we will return early, so caller must always check.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; XLogRecPtr
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;WalSndWaitForWal&lt;/span&gt;(XLogRecPtr loc)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (;;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//收到got_STOPPING信息后，做一次flush wal操作
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//这是必须的！因为walwriter进程在此时可能已经关闭了，可能还有wal没有刷盘
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (got_STOPPING)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;XLogBackgroundFlush&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* Update our idea of the currently flushed position. */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;RecoveryInProgress&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			RecentFlushPtr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;GetFlushRecPtr&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			RecentFlushPtr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;GetXLogReplayRecPtr&lt;/span&gt;(NULL);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//跳出for循环
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//有了新的RecentFlushPtr位置后，还需要send
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (got_STOPPING)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/* reactivate latch so WalSndLoop knows to continue */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;SetLatch&lt;/span&gt;(MyLatch);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; RecentFlushPtr;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;回到walsender主循环：&lt;code&gt;WalSndLoop(XLogSendLogical)&lt;/code&gt;;&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/* Main loop of walsender process that streams the WAL over Copy messages. */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;WalSndLoop&lt;/span&gt;(WalSndSendDataCallback send_data)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (;;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* Clear any already-pending wakeups */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;ResetLatch&lt;/span&gt;(MyLatch);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;//处理下游返回的信息
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;ProcessRepliesIfAny&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * If we have received CopyDone from the client, sent CopyDone
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * ourselves, and the output buffer is empty, it&amp;#39;s time to exit
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * streaming.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//streaming做完就退出循环
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (streamingDoneReceiving &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; streamingDoneSending &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pq_is_send_pending&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//output buffer是否还有pending的data，有就send
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pq_is_send_pending&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;send_data&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			WalSndCaughtUp &lt;span style="color:#f92672"&gt;=&lt;/span&gt; false;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* Try to flush pending output to the client */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;pq_flush_if_writable&lt;/span&gt;() &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;WalSndShutdown&lt;/span&gt;();&lt;span style="color:#75715e"&gt;//下游不可写入，下游端关闭了，正常关闭walsender，退出码0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* If nothing remains to be sent right now ... */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (WalSndCaughtUp &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pq_is_send_pending&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * If we&amp;#39;re in catchup state, move to streaming. This is an
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * important state change for users to know about, since before
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * this point data loss might occur if the primary dies and we
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * need to failover to the standby. The state change is also
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * important for synchronous replication, since commits that
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * started to wait at that point might wait for some time.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//数据已经传完了，但是仍然要发送提交信息
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (MyWalSnd&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;state &lt;span style="color:#f92672"&gt;==&lt;/span&gt; WALSNDSTATE_CATCHUP)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;ereport&lt;/span&gt;(DEBUG1,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						(&lt;span style="color:#a6e22e"&gt;errmsg&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;%s&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt; has now caught up with upstream server&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;								application_name)));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;WalSndSetState&lt;/span&gt;(WALSNDSTATE_STREAMING);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//收到SIGUSR2，表示shutdown checkpoint做完了。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//把shutdown checkpoint record发出去，等待完成再退出
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (got_SIGUSR2)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;WalSndDone&lt;/span&gt;(send_data);&lt;span style="color:#75715e"&gt;//退出码0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;走远了，回到checkpointer的&lt;code&gt;ShutdownXLOG&lt;/code&gt;逻辑，以上只是在分析&lt;code&gt;WalSndInitStopping()&lt;/code&gt;。这个信号发送给walsender后，会执行&lt;code&gt;WalSndWaitStopping&lt;/code&gt;以等待walsender。&lt;/p&gt;
&lt;p&gt;只要有walsender没有退出，这里就是一个死循环不会return：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Wait that all the WAL senders have quit or reached the stopping state. This
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * is used by the checkpointer to control when the shutdown checkpoint can
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * safely be performed.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;WalSndWaitStopping&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (;;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;			i;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt;		all_stopped &lt;span style="color:#f92672"&gt;=&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (i &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; i &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; max_wal_senders; i&lt;span style="color:#f92672"&gt;++&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			WalSnd	 &lt;span style="color:#f92672"&gt;*&lt;/span&gt;walsnd &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;WalSndCtl&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;walsnds[i];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;SpinLockAcquire&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;walsnd&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;mutex);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (walsnd&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;pid &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;SpinLockRelease&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;walsnd&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;mutex);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;continue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (walsnd&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;state &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; WALSNDSTATE_STOPPING)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				all_stopped &lt;span style="color:#f92672"&gt;=&lt;/span&gt; false;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;SpinLockRelease&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;walsnd&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;mutex);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;SpinLockRelease&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;walsnd&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;mutex);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* safe to leave if confirmation is done for all WAL senders */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (all_stopped)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;pg_usleep&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;10000L&lt;/span&gt;);		&lt;span style="color:#75715e"&gt;/* wait for 10 msec */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;最后结合walsender.c的注释：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; If the server is shut down, checkpointer sends us
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; PROCSIG_WALSND_INIT_STOPPING after all regular backends have exited. If
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; the backend is idle or runs an SQL query this causes the backend to
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; shutdown, &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; logical replication is in progress all existing WAL records
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; are processed followed by a shutdown. Otherwise this causes the walsender
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; to &lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; to the &lt;span style="color:#e6db74"&gt;&amp;#34;stopping&amp;#34;&lt;/span&gt; state. In this state, the walsender will reject
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; any further replication commands. The checkpointer begins the shutdown
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; checkpoint once all walsenders are confirmed as stopping. When the shutdown
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; checkpoint finishes, the postmaster sends us SIGUSR2. This instructs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; walsender to send any outstanding WAL, including the shutdown checkpoint
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; record, wait &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; it to be replicated to the standby, and then exit.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;当所有的常规backend都退出后，checkpointer会发送&lt;code&gt;PROCSIG_WALSND_INIT_STOPPING&lt;/code&gt;给walsender&lt;/li&gt;
&lt;li&gt;walsender可能进入stopping状态&lt;/li&gt;
&lt;li&gt;当所有walsender都进入stopping状态后，checkpointer才会做shutdown checkpoint&lt;/li&gt;
&lt;li&gt;当shutdown checkpoint完成后，pm发送&lt;code&gt;SIGUSR2&lt;/code&gt;给walsender，walsender会发送额外的wal，包括shutdown checkpoint记录本身，并等待standby完成再退出&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;停库流程图
 &lt;div id="停库流程图" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%81%9c%e5%ba%93%e6%b5%81%e7%a8%8b%e5%9b%be" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;撸完源码好像懂了又好像没懂，需要一个停库流程图来理清思路。
汇总fast shutdown停库流程图：



&lt;img src="https://lastdba.com/img/csdn/464a8c3e13dd.png" alt="pg fast停库流程.png" /&gt;&lt;/p&gt;
&lt;p&gt;（高清大图：&lt;a href="https://www.processon.com/view/link/6778a73a04a8344b9502637a" target="_blank" rel="noreferrer"&gt;https://www.processon.com/view/link/6778a73a04a8344b9502637a&lt;/a&gt;）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PG通过信号、各进程主循环、PM状态机、pmdie进程回收函数来共同管理停库逻辑&lt;/li&gt;
&lt;li&gt;还需注意：信号本身是异步的。如果需要等待目标进程处理信号的结果，通常需要通过其他同步机制（如管道、信号量、共享内存等）来实现。PG主要通过进程依赖和进程是否正常退出来判断信号是否被正确处理。&lt;/li&gt;
&lt;li&gt;pgarch、walsender被认为是同一类进程，与其他进程（walwriter、bgwriter）等处理不同。pgarch、walsender需要额外做“&lt;strong&gt;最后一个任务&lt;/strong&gt;”这件事。“&lt;strong&gt;最后一个任务&lt;/strong&gt;”的信号通常定义为SIGUSR2&lt;/li&gt;
&lt;li&gt;checkpointer的正常退出依赖pgarch、walsender的正常退出&lt;/li&gt;
&lt;li&gt;pgarch的最后一个任务是最后一次归档。所以归档会影响停库&lt;/li&gt;
&lt;li&gt;walsender的倒数第二个任务是传递最后的wal，最后一个任务是传递checkpoint shutdown信息。且这些任务需要下游回复消息，所以walsender会影响停库。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;测试复现
 &lt;div id="测试复现" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%b5%8b%e8%af%95%e5%a4%8d%e7%8e%b0" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;测试：复现walsender阻止停库
 &lt;div id="测试复现walsender阻止停库" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%b5%8b%e8%af%95%e5%a4%8d%e7%8e%b0walsender%e9%98%bb%e6%ad%a2%e5%81%9c%e5%ba%93" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;在fast stop停库后，walsender可能阻止停库。&lt;/p&gt;
&lt;p&gt;测试了各自场景去复现walsender阻止停库，目前来看以下条件同时满足比较容易触发停库异常：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;发布订阅一个walsender&lt;/li&gt;
&lt;li&gt;dts一个walsender&lt;/li&gt;
&lt;li&gt;大量子事务导致复制槽spill中&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这个三合一场景不代表唯一场景，只是测试了很多场景这个好复现一点。&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--复现命令（不是特别稳定的复现）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;.&lt;span style="color:#960050;background-color:#1e0010"&gt;建表&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--pg
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; lzlpg(id bigserial &lt;span style="color:#66d9ef"&gt;primary&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;key&lt;/span&gt;,a char(&lt;span style="color:#ae81ff"&gt;2000&lt;/span&gt;),b char(&lt;span style="color:#ae81ff"&gt;2000&lt;/span&gt;),&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt; char(&lt;span style="color:#ae81ff"&gt;2000&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--oracle
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; lzl.lzloracle(id number &lt;span style="color:#66d9ef"&gt;primary&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;key&lt;/span&gt; ,a char(&lt;span style="color:#ae81ff"&gt;2000&lt;/span&gt;),b char(&lt;span style="color:#ae81ff"&gt;2000&lt;/span&gt;),&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt; char(&lt;span style="color:#ae81ff"&gt;2000&lt;/span&gt;)) tablespace FADATA;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;.&lt;span style="color:#960050;background-color:#1e0010"&gt;搭建&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;条逻辑链路（&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;条发布订阅，一条&lt;/span&gt;dts到oracle&lt;span style="color:#960050;background-color:#1e0010"&gt;）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;.&lt;span style="color:#960050;background-color:#1e0010"&gt;改小&lt;/span&gt;logical_decoding_work_mem
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;logical_decoding_work_mem&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;MB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;.&lt;span style="color:#960050;background-color:#1e0010"&gt;写入大量数据（推荐子事务&lt;/span&gt;spill&lt;span style="color:#960050;background-color:#1e0010"&gt;）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--一次insert一行，每个insert一个子事务
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;echo &lt;span style="color:#e6db74"&gt;&amp;#34;begin;&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;subtx.&lt;span style="color:#66d9ef"&gt;sql&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;{&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;500000&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;savepoint p$i;&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt;subtx.&lt;span style="color:#66d9ef"&gt;sql&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;insert into lzlpg(column1,column2,column3) select &amp;#39;a&amp;#39;,&amp;#39;b&amp;#39;,&amp;#39;c&amp;#39;;&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt;subtx.&lt;span style="color:#66d9ef"&gt;sql&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;done
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nohup psql &lt;span style="color:#f92672"&gt;-&lt;/span&gt;d lzl &lt;span style="color:#f92672"&gt;-&lt;/span&gt;f subtx.&lt;span style="color:#66d9ef"&gt;sql&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#960050;background-color:#1e0010"&gt;没写入完就停库&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pg_ctl stop &lt;span style="color:#f92672"&gt;-&lt;/span&gt;D &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;PGDATA &lt;span style="color:#f92672"&gt;-&lt;/span&gt;m fast&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;此时fast停库，数据库处于一个非完整停库状态，如下:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;~/lzl/slot&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ ps -axjf|grep &lt;span style="color:#ae81ff"&gt;110402&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;150696&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;64964&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;64961&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;146782&lt;/span&gt; pts/42 &lt;span style="color:#ae81ff"&gt;64961&lt;/span&gt; S+ &lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; 0:00 &lt;span style="color:#ae81ff"&gt;\_&lt;/span&gt; grep --color&lt;span style="color:#f92672"&gt;=&lt;/span&gt;auto &lt;span style="color:#ae81ff"&gt;110402&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;110402&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;110402&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;110402&lt;/span&gt; ? -1 Ss &lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; 0:00 /myhost/postgres/base/rasesql1.5.6/bin/postgres -D /myhost/pg8094/data
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;110402&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;110599&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;110599&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;110599&lt;/span&gt; ? -1 Ss &lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; 0:00 &lt;span style="color:#ae81ff"&gt;\_&lt;/span&gt; postgres: lzlpg: logger 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;110402&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;117803&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;117803&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;117803&lt;/span&gt; ? -1 Ss &lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; 0:00 &lt;span style="color:#ae81ff"&gt;\_&lt;/span&gt; postgres: lzlpg: checkpointer 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;110402&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;117807&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;117807&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;117807&lt;/span&gt; ? -1 Ss &lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; 0:00 &lt;span style="color:#ae81ff"&gt;\_&lt;/span&gt; postgres: lzlpg: stats collector 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;110402&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;118563&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;118563&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;118563&lt;/span&gt; ? -1 Rs &lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; 3:29 &lt;span style="color:#ae81ff"&gt;\_&lt;/span&gt; postgres: lzlpg: walsender lzl 127.0.0.1&lt;span style="color:#f92672"&gt;(&lt;/span&gt;62971&lt;span style="color:#f92672"&gt;)&lt;/span&gt; idle
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;110402&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;222918&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;222918&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;222918&lt;/span&gt; ? -1 Rs &lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; 2:59 &lt;span style="color:#ae81ff"&gt;\_&lt;/span&gt; postgres: lzlpg: walsender dtssync 30.181.46.203&lt;span style="color:#f92672"&gt;(&lt;/span&gt;57218&lt;span style="color:#f92672"&gt;)&lt;/span&gt; idle&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;walsender、checkpointer、postmaster都在，logger、stats也没有退出。&lt;/p&gt;
&lt;p&gt;控制文件的状态为&lt;code&gt;in production&lt;/code&gt;：生产运行中，说明checkpoint做的本地shutdown checkpoint没有做完：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;~/lzl/slot&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ pg_controldata|grep -i state
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Database cluster state: in production&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;checkpointer堆栈：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pstack &lt;span style="color:#ae81ff"&gt;117803&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#0 0x00002b879fe0b983 in __select_nocancel () from /lib64/libc.so.6
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#1 0x00000000008fd04a in pg_usleep (microsec=microsec@entry=10000) at pgsleep.c:56
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#2 0x00000000007610c8 in WalSndWaitStopping () at walsender.c:3209
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#3 0x000000000051fa86 in ShutdownXLOG (code=code@entry=0, arg=arg@entry=0) at xlog.c:8596
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#4 0x00000000007215ff in HandleCheckpointerInterrupts () at checkpointer.c:566
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#5 CheckpointerMain () at checkpointer.c:343
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;此时的checkpointer堵在&lt;code&gt;WalSndWaitStopping&lt;/code&gt;函数，代表checkpointer在等待walsender进程进入stopping状态。&lt;/p&gt;
&lt;p&gt;此时的walsender堆栈：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#0 0x00000000007484fb in ReorderBufferLargestTXN (rb=&amp;lt;optimized out&amp;gt;) at reorderbuffer.c:2345
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#1 ReorderBufferCheckMemoryLimit (rb=0x2b8808b94118) at reorderbuffer.c:2390
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#2 ReorderBufferQueueChange (rb=0x2b8808b94118, xid=&amp;lt;optimized out&amp;gt;, lsn=1676456602544, change=change@entry=0x2b87a229f408) at reorderbuffer.c:649
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#3 0x000000000073ec99 in DecodeTruncate (buf=&amp;lt;optimized out&amp;gt;, buf=&amp;lt;optimized out&amp;gt;, ctx=&amp;lt;optimized out&amp;gt;) at decode.c:872
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#4 DecodeHeapOp (buf=0x7ffda7d35180, ctx=0x2b87a224b118) at decode.c:455
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#5 LogicalDecodingProcessRecord (ctx=0x2b87a224b118, record=&amp;lt;optimized out&amp;gt;) at decode.c:126
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#6 0x000000000075f502 in XLogSendLogical () at walsender.c:2886
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#7 0x0000000000761822 in WalSndLoop (send_data=send_data@entry=0x75f4c0 &amp;lt;XLogSendLogical&amp;gt;) at walsender.c:2287
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;walsender堵在事务溢出函数。（&lt;em&gt;为什么堵还没有搞清楚！！！&lt;/em&gt;）&lt;/p&gt;
&lt;p&gt;checkpointer进程阻塞在&lt;code&gt;WalSndWaitStopping&lt;/code&gt;函数：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Wait that all the WAL senders have quit or reached the stopping state. This
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * is used by the checkpointer to control when the shutdown checkpoint can
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * safely be performed.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;WalSndWaitStopping&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (;;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;			i;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt;		all_stopped &lt;span style="color:#f92672"&gt;=&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (i &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; i &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; max_wal_senders; i&lt;span style="color:#f92672"&gt;++&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			WalSnd	 &lt;span style="color:#f92672"&gt;*&lt;/span&gt;walsnd &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;WalSndCtl&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;walsnds[i];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;SpinLockAcquire&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;walsnd&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;mutex);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (walsnd&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;pid &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;SpinLockRelease&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;walsnd&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;mutex);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;continue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (walsnd&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;state &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; WALSNDSTATE_STOPPING)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				all_stopped &lt;span style="color:#f92672"&gt;=&lt;/span&gt; false;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;SpinLockRelease&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;walsnd&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;mutex);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;SpinLockRelease&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;walsnd&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;mutex);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* safe to leave if confirmation is done for all WAL senders */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (all_stopped)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;pg_usleep&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;10000L&lt;/span&gt;);		&lt;span style="color:#75715e"&gt;/* wait for 10 msec */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;从代码和堆栈来看肯定是进入了条件&lt;code&gt;walsnd-&amp;gt;state != WALSNDSTATE_STOPPIN&lt;/code&gt;才会出现跳不出死循环。&lt;/p&gt;

&lt;h3 class="relative group"&gt;测试：停库中间态的处理方案
 &lt;div id="测试停库中间态的处理方案" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%b5%8b%e8%af%95%e5%81%9c%e5%ba%93%e4%b8%ad%e9%97%b4%e6%80%81%e7%9a%84%e5%a4%84%e7%90%86%e6%96%b9%e6%a1%88" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;以上是个尴尬的停库停一半的状态，除了&lt;code&gt;kill -9&lt;/code&gt; 外，实际上还有其他好办法可以一致性停库。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;方案1：关闭下游进程&lt;/li&gt;
&lt;li&gt;方案2：发送&lt;code&gt;SIGTERM&lt;/code&gt;给walsender&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;方案1测试：&lt;/p&gt;
&lt;p&gt;由于下游退出后，walsender也会跟随退出：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;ProcessRepliesIfAny&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 * &amp;#39;X&amp;#39; means that the standby is closing down the socket.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;				 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;X&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;proc_exit&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;如果是发布订阅，在订阅端执行以下命令即可，即使是上游处于停库中间态也会将walsender退出。&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt; lzldb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;alter&lt;/span&gt; SUBSCRIPTION sub_lzl disable;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;不过这依赖下游自身的处理，我们也不能快速地关闭dts等同步工具的下游接收进程。&lt;/p&gt;
&lt;p&gt;方案2测试：&lt;/p&gt;
&lt;p&gt;由于walsender注册了&lt;code&gt;SIGTERM&lt;/code&gt;信号，库运行时跑的&lt;code&gt;select pg_terminate_backend($walsender_pid)&lt;/code&gt;命令也是发送&lt;code&gt;SIGTERM&lt;/code&gt;给walsender，所以理论上只要发送&lt;code&gt;SIGTERM&lt;/code&gt;给walsender应该可以处理这个问题，而不必发送&lt;code&gt;kill -9&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;命令如下：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kill &lt;span style="color:#f92672"&gt;-&lt;/span&gt;SIGTERM &lt;span style="color:#ae81ff"&gt;62834&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;同&lt;/span&gt; kill &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;62834&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;同&lt;/span&gt; kill &lt;span style="color:#ae81ff"&gt;62834&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;正常kill后pm等进程全部退出。&lt;/p&gt;
&lt;p&gt;查看控制文件和wal日志信息以确认是否是一致性停库：&lt;/p&gt;
&lt;p&gt;1.pg_controldata的数据库state从in production转换为shut down一致性停库：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ pg_controldata|grep -i state
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Database cluster state: shut down&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;2.wal日志的最后一个record是&lt;code&gt;CHECKPOINT_SHUTDOWN&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pg_waldump 000000010000018600000012|tail -1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pg_waldump: fatal: error in WAL record at 186/915D7920: invalid record length at 186/915D7998: wanted 24, got &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rmgr: XLOG len &lt;span style="color:#f92672"&gt;(&lt;/span&gt;rec/tot&lt;span style="color:#f92672"&gt;)&lt;/span&gt;: 114/ 114, tx: 0, lsn: 186/915D7920, prev 186/915D78A8, desc: CHECKPOINT_SHUTDOWN redo 186/915D7920; tli 1; prev tli 1; fpw true; xid 0:13431045; oid 3808147; multi 3; offset 6; oldest xid &lt;span style="color:#ae81ff"&gt;485&lt;/span&gt; in DB 1; oldest multi &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; in DB 1; oldest/newest commit timestamp xid: 494/13431044; oldest running xid 0; shutdown&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 class="relative group"&gt;测试：复现只有主库有CHECKPOINT_SHUTDOWN
 &lt;div id="测试复现只有主库有checkpoint_shutdown" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%b5%8b%e8%af%95%e5%a4%8d%e7%8e%b0%e5%8f%aa%e6%9c%89%e4%b8%bb%e5%ba%93%e6%9c%89checkpoint_shutdown" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;生产现场有个现象是，本地wal有shutdown checkpoint但是从库没有。生产是在半停库状态时做的immediate stop，随后启动库没有启动起来。&lt;/p&gt;
&lt;p&gt;当时主从的wal日志最后2条record类似如下：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#主库wal：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CHECKPOINT_ONLINE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CHECKPOINT_SHUTDOWN
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#从库wal：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CHECKPOINT_ONLINE&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;复现命令：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## 1. 先复现walsender阻止停库&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;略
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## 2. 查看最后一条wal record&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rmgr: Standby len &lt;span style="color:#f92672"&gt;(&lt;/span&gt;rec/tot&lt;span style="color:#f92672"&gt;)&lt;/span&gt;: 50/ 50, tx: 0, lsn: 188/307ABE00, prev 188/307ABDC8, desc: RUNNING_XACTS nextXid &lt;span style="color:#ae81ff"&gt;13432445&lt;/span&gt; latestCompletedXid &lt;span style="color:#ae81ff"&gt;13432444&lt;/span&gt; oldestRunningXid &lt;span style="color:#ae81ff"&gt;13432445&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## 3. pg_ctl stop -D $PGDATA -m i&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## 4. 查看最后一条wal record&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;不变，同2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## 5. pg_ctl start -D $PGDATA&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## 6. 查看最后两条wal record&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rmgr: Standby len &lt;span style="color:#f92672"&gt;(&lt;/span&gt;rec/tot&lt;span style="color:#f92672"&gt;)&lt;/span&gt;: 50/ 50, tx: 0, lsn: 188/307ABE00, prev 188/307ABDC8, desc: RUNNING_XACTS nextXid &lt;span style="color:#ae81ff"&gt;13432445&lt;/span&gt; latestCompletedXid &lt;span style="color:#ae81ff"&gt;13432444&lt;/span&gt; oldestRunningXid &lt;span style="color:#ae81ff"&gt;13432445&lt;/span&gt; &lt;span style="color:#75715e"&gt;#同2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rmgr: XLOG len &lt;span style="color:#f92672"&gt;(&lt;/span&gt;rec/tot&lt;span style="color:#f92672"&gt;)&lt;/span&gt;: 114/ 114, tx: 0, lsn: 188/307ABE38, prev 188/307ABE00, desc: CHECKPOINT_SHUTDOWN redo 188/307ABE38; tli 1; prev tli 1; fpw true; xid 0:13432445; oid 3832732; multi 3; offset 6; oldest xid &lt;span style="color:#ae81ff"&gt;485&lt;/span&gt; in DB 1; oldest multi &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; in DB 1; oldest/newest commit timestamp xid: 494/13432444; oldest running xid 0; shutdown &lt;span style="color:#75715e"&gt;#出现CHECKPOINT_SHUTDOWN&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;从该复现来看，&lt;code&gt;CHECKPOINT_SHUTDOWN&lt;/code&gt;其实是&lt;strong&gt;起库&lt;/strong&gt;的时候做！&lt;/p&gt;
&lt;p&gt;这与现场的动作一致：1.fast停库没停下来 2.immediate停库 3.起库没启起来。&lt;/p&gt;
&lt;p&gt;疑问1：起库什么时候做的CHECKPOINT_SHUTDOWN？&lt;/p&gt;
&lt;p&gt;疑问2：CHECKPOINT_ONLINE的触发时机？复现表象来看，偶现fast shutdown出现最后一个wal record为CHECKPOINT_ONLINE&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;疑问1分析：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;起库做shutdown checkpoint，这很容易联想到是startup进程做的。由于之前分析过startup进程的起库流程，我们可以直接定位到函数&lt;code&gt;StartupXLOG&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * This must be called ONCE during postmaster or standalone-backend startup
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;StartupXLOG&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (InRecovery) &lt;span style="color:#75715e"&gt;//因为是shutdown停库所以会做实例恢复
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * Perform a checkpoint to update all our recovery activity to disk.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * Note that we write a shutdown checkpoint rather than an on-line
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * one. This is not particularly critical, but since we may be
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * assigning a new TLI, using a shutdown checkpoint allows us to have
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * the rule that TLI only changes in shutdown checkpoints, which
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * allows some extra error checking in xlog_redo.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * In fast promotion, only create a lightweight end-of-recovery record
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * instead of a full checkpoint. A checkpoint is requested later,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * after we&amp;#39;re fully out of recovery mode and already accepting
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * queries.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (bgwriterLaunched) &lt;span style="color:#75715e"&gt;//这个if明显是从库流复制用的逻辑
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#75715e"&gt;//主库的startup会走到这里
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;CreateCheckPoint&lt;/span&gt;(CHECKPOINT_END_OF_RECOVERY &lt;span style="color:#f92672"&gt;|&lt;/span&gt; CHECKPOINT_IMMEDIATE);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;做shutdown checkpoint是故意的，主要是为了TLI逻辑的代码健壮性&lt;/li&gt;
&lt;li&gt;只要是非一致性停库，起库的时候就会做shutdown checkpoint&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以，直接&lt;code&gt;-m i&lt;/code&gt;暴力停库再起库，也会出现&lt;code&gt;CHECKPOINT_SHUTDOWN&lt;/code&gt;，自测。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;疑问2分析：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;多次测试，偶现，推测是刚好停库前满足checkpoint条件触发了一次online checkpoint，纯属巧合。&lt;/p&gt;
&lt;p&gt;联想数据库停库失败后，无论是脚本、HA还是人工介入都有可能做暴力停库，所以停库前推荐至少做一次checkpoint。&lt;/p&gt;

&lt;h3 class="relative group"&gt;测试：归档对停库的影响
 &lt;div id="测试归档对停库的影响" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%b5%8b%e8%af%95%e5%bd%92%e6%a1%a3%e5%af%b9%e5%81%9c%e5%ba%93%e7%9a%84%e5%bd%b1%e5%93%8d" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;在分析停库代码的时候，还发现checkpointer进程退出后，reaper checkpointer会发送&lt;code&gt;SIGUSR2&lt;/code&gt;给pgarch让其最后一次归档并退出：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;reaper&lt;/span&gt;(SIGNAL_ARGS)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (pid &lt;span style="color:#f92672"&gt;==&lt;/span&gt; CheckpointerPID)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			CheckpointerPID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;EXIT_STATUS_0&lt;/span&gt;(exitstatus) &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pmState &lt;span style="color:#f92672"&gt;==&lt;/span&gt; PM_SHUTDOWN)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			{...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#75715e"&gt;/* Waken archiver for the last time */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (PgArchPID &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;					&lt;span style="color:#a6e22e"&gt;signal_child&lt;/span&gt;(PgArchPID, SIGUSR2);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;而pm的退出依赖除syslogger外所有进程的退出：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (pmState &lt;span style="color:#f92672"&gt;==&lt;/span&gt; PM_WAIT_DEAD_END)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;dlist_is_empty&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;BackendList) &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			PgArchPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; PgStatPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/* These other guys should be dead already */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;Assert&lt;/span&gt;(StartupPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;Assert&lt;/span&gt;(WalReceiverPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;Assert&lt;/span&gt;(BgWriterPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;Assert&lt;/span&gt;(CheckpointerPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;Assert&lt;/span&gt;(WalWriterPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;Assert&lt;/span&gt;(AutoVacPID &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/* syslogger is not considered here */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			pmState &lt;span style="color:#f92672"&gt;=&lt;/span&gt; PM_NO_CHILDREN;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;所以在生产环境中还发现了归档慢对停库有影响。&lt;/p&gt;
&lt;p&gt;复现命令：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;配置归档&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;archive_mode &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;archive_command &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;/bin/false ;sleep 1000&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;配置归档永远为&lt;/span&gt;false且设置sleep以绕过NUM_ARCHIVE_RETRIES逻辑
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;停库&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pg_ctl stop &lt;span style="color:#f92672"&gt;-&lt;/span&gt;D &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;PGDATA &lt;span style="color:#f92672"&gt;-&lt;/span&gt;m fast&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;停库后进程如下：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ ps -axjf|grep &lt;span style="color:#ae81ff"&gt;61470&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;72200&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;88406&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;88405&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;68705&lt;/span&gt; pts/48 &lt;span style="color:#ae81ff"&gt;88405&lt;/span&gt; S+ &lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; 0:00 &lt;span style="color:#ae81ff"&gt;\_&lt;/span&gt; grep --color&lt;span style="color:#f92672"&gt;=&lt;/span&gt;auto &lt;span style="color:#ae81ff"&gt;61470&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;61470&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;61470&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;61470&lt;/span&gt; ? -1 Ss &lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; 0:00 /myhost/postgres/base/rasesql1.5.6/bin/postgres -D /myhost/pg8094/data
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;61470&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;61772&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;61772&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;61772&lt;/span&gt; ? -1 Ss &lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; 0:00 &lt;span style="color:#ae81ff"&gt;\_&lt;/span&gt; postgres: lzlpg: logger 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;61470&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;63880&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;63880&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;63880&lt;/span&gt; ? -1 Ss &lt;span style="color:#ae81ff"&gt;6001&lt;/span&gt; 0:00 &lt;span style="color:#ae81ff"&gt;\_&lt;/span&gt; postgres: lzlpg: archiver archiving &lt;span style="color:#ae81ff"&gt;000000010000018800000007&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;因为这里的checkpointer已经完整停下来了，数据库是一致状态，所以archiver直接&lt;code&gt;kill -9&lt;/code&gt;也没有关系&lt;/p&gt;

&lt;h2 class="relative group"&gt;一句话总结
 &lt;div id="一句话总结" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%b8%80%e5%8f%a5%e8%af%9d%e6%80%bb%e7%bb%93" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;问题1.为什么停库没有停下来？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;walsender阻止了停库。checkpointer给walsender发送SIGUSR1，并无限等待所有walsender进程stopping状态，checkpointer卡在这一步。&lt;/p&gt;
&lt;p&gt;后面停库停下来是因为&lt;code&gt;-m i&lt;/code&gt;暴力停库&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;问题2.walsender阻止停库中间态是否有其他方案优雅停库？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;有。给所有walsender发送&lt;code&gt;SIGTERM&lt;/code&gt;信号，既&lt;code&gt;kill&lt;/code&gt;（or &lt;code&gt;kill -15&lt;/code&gt;、&lt;code&gt;kill -SIGTERM&lt;/code&gt;)。随后checkpointer、postmaster会完整停库。&lt;/p&gt;
&lt;p&gt;walsender启动时注册过&lt;code&gt;SIGTERM&lt;/code&gt;信号，测试来看没有处理不了的情况。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;SIGTERM&lt;/code&gt;也是&lt;code&gt;pg_terminate_backend(pid)&lt;/code&gt;所发送的信号，也是标准停库时应该执行的命令以停止walsender。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;问题3.为什么主从库只差一条&lt;code&gt;shutdown checkpoint&lt;/code&gt;？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;3.1主从库都有&lt;code&gt;CHECKPOINT_ONLINE&lt;/code&gt; 的解释：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;主库触发&lt;code&gt;CHECKPOINT_ONLINE&lt;/code&gt;纯属巧合&lt;/li&gt;
&lt;li&gt;由于物理walsender还在，这条wal record传输到了从库&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;3.2只有主库有&lt;code&gt;CHECKPOINT_SHUTDOWN&lt;/code&gt;的解释：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;这条&lt;code&gt;CHECKPOINT_SHUTDOWN&lt;/code&gt;是主库起库的时候做的&lt;/li&gt;
&lt;li&gt;由于主库没有起完，这条wal record没有传到从库&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;问题4.archiver为什么会阻止停库？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在reaper checkpointer进程时，pm会让archiver做最后一次归档，而pm依赖除syslogger之外的所有进程退出，所以最后一次归档如果够慢或者其他问题，会阻止停库。归档失败不会，归档进程会很快退出。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;问题5.哪些进程会阻止停库？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;其实任意进程不退出都会阻止停库，问题在于哪些比较容易搞出事。从停库代码流程来看archiver、walsender会常阻止停库，因为他们在停库阶段会做最后一次归档or日志传递。&lt;/p&gt;

&lt;h2 class="relative group"&gt;references
 &lt;div id="references" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#references" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.postgresql.org/docs/current/server-shutdown.html" target="_blank" rel="noreferrer"&gt;https://www.postgresql.org/docs/current/server-shutdown.html&lt;/a&gt;
&lt;a href="https://wiki.postgresql.org/wiki/Signals" target="_blank" rel="noreferrer"&gt;https://wiki.postgresql.org/wiki/Signals&lt;/a&gt;
postgres.c
postmaster.c
walsender.c
xlog.c
checkpointer.c
startup.c
pgarch.c&lt;/p&gt;</content:encoded></item><item><title>PostgreSQL案例：planning time超长问题分析</title><link>https://lastdba.com/2024/08/21/postgresql%E6%A1%88%E4%BE%8Bplanning-time%E8%B6%85%E9%95%BF%E9%97%AE%E9%A2%98%E5%88%86%E6%9E%90/</link><pubDate>Wed, 21 Aug 2024 00:00:00 +0000</pubDate><guid>https://lastdba.com/2024/08/21/postgresql%E6%A1%88%E4%BE%8Bplanning-time%E8%B6%85%E9%95%BF%E9%97%AE%E9%A2%98%E5%88%86%E6%9E%90/</guid><description>&lt;h2 class="relative group"&gt;问题分析概述
 &lt;div id="问题分析概述" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e5%88%86%e6%9e%90%e6%a6%82%e8%bf%b0" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;库总是OOM，分析到是执行计划生成有问题，planning time 1秒，planning shared hit 100w。一通分析，定位到是统计信息基表pg_statistic膨胀，由于会话首次SQL执行时的CatCacheMiss，导致backend访问并缓存了pg_statistic过多的死元组数据。应用连接总会启用新会话，多个backend的总内存过大从而导致OOM。&lt;/p&gt;</description><content:encoded>
&lt;h2 class="relative group"&gt;问题分析概述
 &lt;div id="问题分析概述" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e5%88%86%e6%9e%90%e6%a6%82%e8%bf%b0" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;库总是OOM，分析到是执行计划生成有问题，planning time 1秒，planning shared hit 100w。一通分析，定位到是统计信息基表pg_statistic膨胀，由于会话首次SQL执行时的CatCacheMiss，导致backend访问并缓存了pg_statistic过多的死元组数据。应用连接总会启用新会话，多个backend的总内存过大从而导致OOM。&lt;/p&gt;
&lt;p&gt;下面是详细分析过程。&lt;/p&gt;

&lt;h2 class="relative group"&gt;问题现象
 &lt;div id="问题现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;某库反复OOM和重启。经过一通问题排查，发现会话连接数不多，但是每个会话的内存占用比较高，总内存超过内存cg限制导致OOM。
初步可以排除以下原因：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不是元数据过多的问题导致。对象过多（一般是分区数太多）会导致会话缓存过多的元数据。这个库的对象不算多&lt;/li&gt;
&lt;li&gt;不是sql执行计划问题。排序/hash可能使用过多内存。这个库不是这个场景，sql可以是一个顺序扫描。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在问题分析过程中发现，库里面执行任意一个简单sql执行时间很长，并且 Planning Buffers有约100w&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt;,buffers,timing) &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzlinfo &lt;span style="color:#66d9ef"&gt;limit&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--------------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Limit&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;71&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;011&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;012&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Seq Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzlinfo (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;480&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;73&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;473&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;71&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;010&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;010&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1127312&lt;/span&gt; &lt;span style="color:#75715e"&gt;--异常planning shared hit
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning Time: &lt;span style="color:#ae81ff"&gt;947&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;038&lt;/span&gt; ms &lt;span style="color:#75715e"&gt;--异常planning time
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Execution Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;035&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;再执行一次sql，planning time就正常了。&lt;/p&gt;

&lt;h2 class="relative group"&gt;问题定位过程
 &lt;div id="问题定位过程" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e5%ae%9a%e4%bd%8d%e8%bf%87%e7%a8%8b" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;打印执行计划的stat信息
 &lt;div id="打印执行计划的stat信息" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%89%93%e5%8d%b0%e6%89%a7%e8%a1%8c%e8%ae%a1%e5%88%92%e7%9a%84stat%e4%bf%a1%e6%81%af" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;把会话的执行计划各阶段的stat信息打到日志：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; log_parser_stats &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;on&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; log_planner_stats &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;on&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; log_executor_stats &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;on&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;然后跑下sql，日志输出如下：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-08-13 10:02:33.936 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;postgres&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,85532,&lt;span style="color:#e6db74"&gt;&amp;#34;[local]&amp;#34;&lt;/span&gt;,66babe8c.14e1c,13,&lt;span style="color:#e6db74"&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;,2024-08-13 10:01:48 CST,4/713,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;PARSER STATISTICS&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;! system usage stats:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;! 0.000046 s user, 0.000046 s system, 0.000091 s elapsed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;! [0.001661 s user, 0.001661 s system total]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;! 4660 kB max resident size
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;! 0/0 [0/8] filesystem blocks in/out
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;! 0/36 [0/996] page faults/reclaims, 0 [0] swaps
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;! 0 [0] signals rcvd, 0/0 [0/0] messages rcvd/sent
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;! 0/0 [5/0] voluntary/involuntary context switches&amp;#34;&lt;/span&gt;,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;explain (analyze,buffers) select *,1 from lzlinfo
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;2024-08-13 10:02:33.938 CST,&amp;#34;&lt;/span&gt;postgres&lt;span style="color:#e6db74"&gt;&amp;#34;,&amp;#34;&lt;/span&gt;lzldb&lt;span style="color:#e6db74"&gt;&amp;#34;,85532,&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;local&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;,66babe8c.14e1c,14,&amp;#34;&lt;/span&gt;EXPLAIN&lt;span style="color:#e6db74"&gt;&amp;#34;,2024-08-13 10:01:48 CST,4/713,0,LOG,00000,&amp;#34;&lt;/span&gt;PARSE ANALYSIS STATISTICS&lt;span style="color:#e6db74"&gt;&amp;#34;,&amp;#34;&lt;/span&gt;! system usage stats:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;! 0.001459 s user, 0.000000 s system, 0.001464 s elapsed
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;! &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0.003146 s user, 0.001687 s system total&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;! &lt;span style="color:#ae81ff"&gt;5972&lt;/span&gt; kB max resident size
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;! 0/0 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0/8&lt;span style="color:#f92672"&gt;]&lt;/span&gt; filesystem blocks in/out
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;! 0/325 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0/1324&lt;span style="color:#f92672"&gt;]&lt;/span&gt; page faults/reclaims, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0&lt;span style="color:#f92672"&gt;]&lt;/span&gt; swaps
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;! &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0&lt;span style="color:#f92672"&gt;]&lt;/span&gt; signals rcvd, 0/0 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0/0&lt;span style="color:#f92672"&gt;]&lt;/span&gt; messages rcvd/sent
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;! 0/0 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;5/0&lt;span style="color:#f92672"&gt;]&lt;/span&gt; voluntary/involuntary context switches&lt;span style="color:#e6db74"&gt;&amp;#34;,,,,,&amp;#34;&lt;/span&gt;explain &lt;span style="color:#f92672"&gt;(&lt;/span&gt;analyze,buffers&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; *,1 from lzlinfo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-08-13 10:02:33.938 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;postgres&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,85532,&lt;span style="color:#e6db74"&gt;&amp;#34;[local]&amp;#34;&lt;/span&gt;,66babe8c.14e1c,15,&lt;span style="color:#e6db74"&gt;&amp;#34;EXPLAIN&amp;#34;&lt;/span&gt;,2024-08-13 10:01:48 CST,4/713,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;REWRITER STATISTICS&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;! system usage stats:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;! 0.000001 s user, 0.000000 s system, 0.000001 s elapsed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;! [0.003177 s user, 0.001687 s system total]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;! 5972 kB max resident size
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;! 0/0 [0/8] filesystem blocks in/out
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;! 0/0 [0/1324] page faults/reclaims, 0 [0] swaps
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;! 0 [0] signals rcvd, 0/0 [0/0] messages rcvd/sent
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;! 0/0 [5/0] voluntary/involuntary context switches&amp;#34;&lt;/span&gt;,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;explain (analyze,buffers) select *,1 from lzlinfo
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;2024-08-13 10:02:34.644 CST,&amp;#34;&lt;/span&gt;postgres&lt;span style="color:#e6db74"&gt;&amp;#34;,&amp;#34;&lt;/span&gt;lzldb&lt;span style="color:#e6db74"&gt;&amp;#34;,85532,&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;local&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;,66babe8c.14e1c,16,&amp;#34;&lt;/span&gt;EXPLAIN&lt;span style="color:#e6db74"&gt;&amp;#34;,2024-08-13 10:01:48 CST,4/713,0,LOG,00000,&amp;#34;&lt;/span&gt;PLANNER STATISTICS&lt;span style="color:#e6db74"&gt;&amp;#34;,&amp;#34;&lt;/span&gt;! system usage stats:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;! 0.539964 s user, 0.164083 s system, 0.705718 s elapsed
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;! &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0.543248 s user, 0.165770 s system total&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;! &lt;span style="color:#ae81ff"&gt;745072&lt;/span&gt; kB max resident size --异常点
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;! 0/0 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0/8&lt;span style="color:#f92672"&gt;]&lt;/span&gt; filesystem blocks in/out
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;! 0/184803 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0/186157&lt;span style="color:#f92672"&gt;]&lt;/span&gt; page faults/reclaims, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0&lt;span style="color:#f92672"&gt;]&lt;/span&gt; swaps
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;! &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0&lt;span style="color:#f92672"&gt;]&lt;/span&gt; signals rcvd, 0/0 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0/0&lt;span style="color:#f92672"&gt;]&lt;/span&gt; messages rcvd/sent
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;! 0/1 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;5/1&lt;span style="color:#f92672"&gt;]&lt;/span&gt; voluntary/involuntary context switches&lt;span style="color:#e6db74"&gt;&amp;#34;,,,,,&amp;#34;&lt;/span&gt;explain &lt;span style="color:#f92672"&gt;(&lt;/span&gt;analyze,buffers&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; *,1 from lzlinfo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-08-13 10:02:34.644 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;postgres&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,85532,&lt;span style="color:#e6db74"&gt;&amp;#34;[local]&amp;#34;&lt;/span&gt;,66babe8c.14e1c,17,&lt;span style="color:#e6db74"&gt;&amp;#34;EXPLAIN&amp;#34;&lt;/span&gt;,2024-08-13 10:01:48 CST,4/713,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;EXECUTOR STATISTICS&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;! system usage stats:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;! 0.540248 s user, 0.164170 s system, 0.706088 s elapsed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;! [0.543532 s user, 0.165857 s system total]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;! 745596 kB max resident size
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;! 0/0 [0/8] filesystem blocks in/out
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;! 0/184898 [0/186252] page faults/reclaims, 0 [0] swaps
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;! 0 [0] signals rcvd, 0/0 [0/0] messages rcvd/sent
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;! 0/1 [5/1] voluntary/involuntary context switches&amp;#34;&lt;/span&gt;,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;explain (analyze,buffers) select *,1 from lzlinfo
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;planner阶段内存使用率暴涨，elapsed time也暴涨。这部分信息可以定位到是整个planning阶段中的planner阶段有问题。其他可用信息不多。&lt;/p&gt;

&lt;h3 class="relative group"&gt;strace追踪
 &lt;div id="strace追踪" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#strace%e8%bf%bd%e8%b8%aa" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;strace -p &lt;span style="color:#ae81ff"&gt;76419&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;strace: Process &lt;span style="color:#ae81ff"&gt;76419&lt;/span&gt; attached
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;epoll_wait(&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, [&lt;span style="color:#960050;background-color:#1e0010"&gt;{&lt;/span&gt;EPOLLIN, &lt;span style="color:#960050;background-color:#1e0010"&gt;{&lt;/span&gt;u32&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;15422552&lt;/span&gt;, u64&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;15422552&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;}}&lt;/span&gt;], &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;recvfrom(&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Q\0\0\0\262explain (analyze,buffers) s&amp;#34;&lt;/span&gt;..., &lt;span style="color:#ae81ff"&gt;8192&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;179&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lseek(&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, SEEK_END) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8192&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk(&lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;xfed000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x100e000) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x100e000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk(&lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x100e000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk(&lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x100e000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x1007000) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x1007000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk(&lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x1007000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mmap(&lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;270336&lt;/span&gt;, PROT_READ&lt;span style="color:#f92672"&gt;|&lt;/span&gt;PROT_WRITE, MAP_PRIVATE&lt;span style="color:#f92672"&gt;|&lt;/span&gt;MAP_ANONYMOUS, &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x2b7806b0c000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;open&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;base/17076/16678&amp;#34;&lt;/span&gt;, O_RDWR) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lseek(&lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, SEEK_END) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;open&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;base/17076/46160&amp;#34;&lt;/span&gt;, O_RDWR) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lseek(&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, SEEK_END) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7667712&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;open&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;base/17076/46168&amp;#34;&lt;/span&gt;, O_RDWR) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lseek(&lt;span style="color:#ae81ff"&gt;13&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, SEEK_END) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;188416&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;open&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;base/17076/46170&amp;#34;&lt;/span&gt;, O_RDWR) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lseek(&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, SEEK_END) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;188416&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mmap(&lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;528384&lt;/span&gt;, PROT_READ&lt;span style="color:#f92672"&gt;|&lt;/span&gt;PROT_WRITE, MAP_PRIVATE&lt;span style="color:#f92672"&gt;|&lt;/span&gt;MAP_ANONYMOUS, &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x2b78c1b36000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk(&lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x1007000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x102c000) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x102c000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk(&lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x102c000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk(&lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x102c000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x1025000) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x1025000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk(&lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x1025000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lseek(&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, SEEK_END) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7667712&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;open&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;pg_stat_tmp/pgss_query_texts.stat&amp;#34;&lt;/span&gt;, O_RDWR&lt;span style="color:#f92672"&gt;|&lt;/span&gt;O_CREAT, &lt;span style="color:#ae81ff"&gt;0600&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pwrite64(&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;explain (analyze,buffers) select&amp;#34;&lt;/span&gt;..., &lt;span style="color:#ae81ff"&gt;172&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;93934&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;172&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pwrite64(&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;\0&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;94106&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;close&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sendto(&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;\2\0\0\0\250\3\0\0\264B\0\0\10\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&amp;#34;&lt;/span&gt;..., &lt;span style="color:#ae81ff"&gt;936&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;936&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sendto(&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;\2\0\0\0\250\3\0\0\264B\0\0\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&amp;#34;&lt;/span&gt;..., &lt;span style="color:#ae81ff"&gt;936&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;936&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sendto(&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;\2\0\0\0\250\3\0\0\264B\0\0\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&amp;#34;&lt;/span&gt;..., &lt;span style="color:#ae81ff"&gt;936&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;936&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sendto(&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;\2\0\0\0\250\3\0\0\264B\0\0\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&amp;#34;&lt;/span&gt;..., &lt;span style="color:#ae81ff"&gt;936&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;936&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sendto(&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;\2\0\0\0\250\3\0\0\264B\0\0\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&amp;#34;&lt;/span&gt;..., &lt;span style="color:#ae81ff"&gt;936&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;936&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sendto(&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;\2\0\0\0\10\1\0\0\264B\0\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&amp;#34;&lt;/span&gt;..., &lt;span style="color:#ae81ff"&gt;264&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;264&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sendto(&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;\2\0\0\0\10\1\0\0\0\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&amp;#34;&lt;/span&gt;..., &lt;span style="color:#ae81ff"&gt;264&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;264&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sendto(&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;\16\0\0\0H\0\0\0\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\0\0\0\0&amp;#34;&lt;/span&gt;..., &lt;span style="color:#ae81ff"&gt;72&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;72&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sendto(&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;T\0\0\0#\0\1QUERY PLAN\0\0\0\0\0\0\0\0\0\0\31\377\377\377\377&amp;#34;&lt;/span&gt;..., &lt;span style="color:#ae81ff"&gt;826&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;826&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;recvfrom(&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;xd2b4e0, &lt;span style="color:#ae81ff"&gt;8192&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; EAGAIN (Resource temporarily unavailable)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;epoll_wait(&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;虽然shared hit很多，但strace信息很少
strace显示会话只open了4个数据文件，通过fd和oid2name查到数据文件，分别是表、表的两个索引以及pathman_config：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;From database &lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filenode Table Name
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;46170&lt;/span&gt; ix_name
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;46168&lt;/span&gt; pk_lzlinfo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;46160&lt;/span&gt; lzlinfo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;16678&lt;/span&gt; pathman_config&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这些对象都不大，看上去不像这些表（or索引）过大导致的。&lt;/p&gt;

&lt;h3 class="relative group"&gt;perf
 &lt;div id="perf" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#perf" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;（图不好贴自行脑补）
perf火焰图有40%的时间在&lt;code&gt;heap_hot_search_buffer&lt;/code&gt;堆栈上&lt;/p&gt;

&lt;h3 class="relative group"&gt;gdb
 &lt;div id="gdb" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#gdb" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;以&lt;code&gt;heap_hot_search_buffe&lt;/code&gt;函数为依据，经过多次gdb，打如下断点试着看看哪有问题：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;b relation_open
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;b get_relation_info
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;b RelationCacheInvalidateEntry 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;b get_relname_relid
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;b AcceptInvalidationMessages
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;b RelationClearRelation
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;b pg_hint_plan_planner
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;b heap_hot_search_buffer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;刚开始命中断点的时候，其实有很多无用的信息，因为他们是正常逻辑。不过后面发现，执行&lt;strong&gt;到一定程度&lt;/strong&gt;，只有&lt;code&gt;heap_hot_search_buffer&lt;/code&gt;命中：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Breakpoint 15, heap_hot_search_buffer &lt;span style="color:#f92672"&gt;(&lt;/span&gt;tid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;tid@entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;0x2313c60, relation&lt;span style="color:#f92672"&gt;=&lt;/span&gt;0x2b2141663910, buffer&lt;span style="color:#f92672"&gt;=&lt;/span&gt;17045, snapshot&lt;span style="color:#f92672"&gt;=&lt;/span&gt;snapshot@entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;0x228a058, heapTuple&lt;span style="color:#f92672"&gt;=&lt;/span&gt;heapTuple@entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;0x23273d0, 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; all_dead&lt;span style="color:#f92672"&gt;=&lt;/span&gt;all_dead@entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;0x7ffce272e28f, first_call&lt;span style="color:#f92672"&gt;=&lt;/span&gt;true&lt;span style="color:#f92672"&gt;)&lt;/span&gt; at heapam.c:1503
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;1503&lt;/span&gt; in heapam.c
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;(&lt;/span&gt;gdb&lt;span style="color:#f92672"&gt;)&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Continuing.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Breakpoint 15, heap_hot_search_buffer &lt;span style="color:#f92672"&gt;(&lt;/span&gt;tid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;tid@entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;0x2313c60, relation&lt;span style="color:#f92672"&gt;=&lt;/span&gt;0x2b2141663910, buffer&lt;span style="color:#f92672"&gt;=&lt;/span&gt;96708, snapshot&lt;span style="color:#f92672"&gt;=&lt;/span&gt;snapshot@entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;0x228a058, heapTuple&lt;span style="color:#f92672"&gt;=&lt;/span&gt;heapTuple@entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;0x23273d0, 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; all_dead&lt;span style="color:#f92672"&gt;=&lt;/span&gt;all_dead@entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;0x7ffce272e28f, first_call&lt;span style="color:#f92672"&gt;=&lt;/span&gt;true&lt;span style="color:#f92672"&gt;)&lt;/span&gt; at heapam.c:1503
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;1503&lt;/span&gt; in heapam.c&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;heap_hot_search_buffer&lt;/code&gt;传入的绝大部分参数没有变，包括relation、heapTuple的地址，只有buffer参数在改变，说明应该在扫描同一个relation。&lt;br&gt;
&lt;code&gt;heapTuple&lt;/code&gt;中包含table oid信息，直接打出来看看：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;(&lt;/span&gt;gdb&lt;span style="color:#f92672"&gt;)&lt;/span&gt; p *heapTuple
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$46 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; t_len &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 968, 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; t_self &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ip_blkid &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; bi_hi &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0, 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; bi_lo &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7211&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ip_posid &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; t_tableOid &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 2619, --这个比较有用
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; t_data &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x2b2155fced00&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;heap_hot_search_buffer&lt;/code&gt;传入的oid=2619，2619在pg_class中对应&lt;code&gt;pg_statistic&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; oid,relname &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_class &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; oid &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;2619&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; oid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; relname 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-------+----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;2619&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; pg_statistic&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;找这个统计信息基表无可厚非，因为pg在生成可能的执行计划s时需要用到统计信息来估算代价。&lt;/p&gt;

&lt;h3 class="relative group"&gt;pg_statistic的膨胀
 &lt;div id="pg_statistic的膨胀" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#pg_statistic%e7%9a%84%e8%86%a8%e8%83%80" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;定位到pg_statistic，那么看下pg_statistic表的情况&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;dt&lt;span style="color:#f92672"&gt;+&lt;/span&gt; pg_statistic
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; List &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; relations
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Schema&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Name &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Type&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Owner&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Persistence &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Size&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Description 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;------------+--------------+-------+----------+-------------+---------+-------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pg_catalog &lt;span style="color:#f92672"&gt;|&lt;/span&gt; pg_statistic &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; postgres &lt;span style="color:#f92672"&gt;|&lt;/span&gt; permanent &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1036&lt;/span&gt; MB &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_class &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; relname&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;pg_statistic&amp;#39;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;gx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;[ RECORD &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; ]&lt;span style="color:#75715e"&gt;-------+------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;oid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2619&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;relname &lt;span style="color:#f92672"&gt;|&lt;/span&gt; pg_statistic
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;relnamespace &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;reltype &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;12016&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;reloftype &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;relowner &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;relam &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;relfilenode &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2619&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;reltablespace &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;relpages &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;132481&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;reltuples &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4655&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;pg_statistic&lt;/code&gt;有1G，确实有些大了， 有132481块却只有4655行，这明显是有表膨胀了。但是即便有表膨胀，访问统计信息需要cache整个pg_statistic吗？逻辑上来说不需要，因为只需要访问对应表的统计信息就行了，实际上pg也是通过&lt;code&gt;pg_statistic&lt;/code&gt;的主键索引&lt;code&gt;pg_statistic_relid_att_inh_index&lt;/code&gt;来访问的。从下面的从堆栈中能看到传入的是&lt;code&gt;pg_statistic&lt;/code&gt;的复合主键上的字段：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x000000000086edbc &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; SearchCatCacheMiss (&lt;span style="color:#66d9ef"&gt;cache&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;cache&lt;/span&gt;&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x226ba80, nkeys&lt;span style="color:#f92672"&gt;=&lt;/span&gt;nkeys&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, hashValue&lt;span style="color:#f92672"&gt;=&lt;/span&gt;hashValue&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;853716409&lt;/span&gt;, hashIndex&lt;span style="color:#f92672"&gt;=&lt;/span&gt;hashIndex&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;57&lt;/span&gt;, v1&lt;span style="color:#f92672"&gt;=&lt;/span&gt;v1&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;18767&lt;/span&gt;, v2&lt;span style="color:#f92672"&gt;=&lt;/span&gt;v2&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; v3&lt;span style="color:#f92672"&gt;=&lt;/span&gt;v3&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, v4&lt;span style="color:#f92672"&gt;=&lt;/span&gt;v4&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; catcache.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;1368&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;7&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x000000000086fa82 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; SearchCatCacheInternal (v4&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, v3&lt;span style="color:#f92672"&gt;=&amp;lt;&lt;/span&gt;optimized &lt;span style="color:#66d9ef"&gt;out&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;, v2&lt;span style="color:#f92672"&gt;=&amp;lt;&lt;/span&gt;optimized &lt;span style="color:#66d9ef"&gt;out&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;, v1&lt;span style="color:#f92672"&gt;=&amp;lt;&lt;/span&gt;optimized &lt;span style="color:#66d9ef"&gt;out&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;, nkeys&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;cache&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x226ba80) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; catcache.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;1299&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; SearchCatCache3 (&lt;span style="color:#66d9ef"&gt;cache&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x226ba80, v1&lt;span style="color:#f92672"&gt;=&lt;/span&gt;v1&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;18767&lt;/span&gt;, v2&lt;span style="color:#f92672"&gt;=&lt;/span&gt;v2&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, v3&lt;span style="color:#f92672"&gt;=&lt;/span&gt;v3&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; catcache.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;1183&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x0000000000880d70 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; SearchSysCache3 (cacheId&lt;span style="color:#f92672"&gt;=&lt;/span&gt;cacheId&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;58&lt;/span&gt;, key1&lt;span style="color:#f92672"&gt;=&lt;/span&gt;key1&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;18767&lt;/span&gt;, key2&lt;span style="color:#f92672"&gt;=&lt;/span&gt;key2&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, key3&lt;span style="color:#f92672"&gt;=&lt;/span&gt;key3&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; syscache.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;1145&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x0000000000874092 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; get_attavgwidth (relid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;relid&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;18767&lt;/span&gt;, attnum&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; lsyscache.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;2991&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;11&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x00000000006a2d46 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; set_rel_width (root&lt;span style="color:#f92672"&gt;=&lt;/span&gt;root&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x2326600, rel&lt;span style="color:#f92672"&gt;=&lt;/span&gt;rel&lt;span style="color:#f92672"&gt;@&lt;/span&gt;entry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;x21e8418) &lt;span style="color:#66d9ef"&gt;at&lt;/span&gt; costsize.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;5516&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;传入了&lt;code&gt;relid=relid@entry=18767, attnum=1&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; ctid,starelid,staattnum &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_statistic &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; starelid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;18767&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ctid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; starelid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; staattnum 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;------------+----------+-----------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;132657&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;) &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;18767&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;132657&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;) &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;18767&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;132657&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;) &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;18767&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;132657&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;) &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;18767&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;132658&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;18767&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;132658&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;) &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;18767&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;132658&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;) &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;18767&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;132658&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;) &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;18767&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;132658&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;) &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;18767&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;132658&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;) &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;18767&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;--lzlinfo总共10个字段，每个字段对应一个staattnum&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;通过ctid可以看出，这些数据实际上只在2个块中。
看下通过复合主键索引访问&lt;code&gt;pg_statistic&lt;/code&gt;，结果发现哪怕在只有2个块，也要访问1s，shared hit高达100w（1141568）：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt;,buffers,timing,&lt;span style="color:#66d9ef"&gt;verbose&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; ctid,starelid &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_statistic &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; starelid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;18767&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--------------------------------------------------------------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; pg_statistic_relid_att_inh_index &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; pg_catalog.pg_statistic (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;41&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;103&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;31&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;105&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;416&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;1035&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;723&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Output&lt;/span&gt;: ctid, starelid
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (pg_statistic.starelid &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;18767&amp;#39;&lt;/span&gt;::oid)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1141568&lt;/span&gt; &lt;span style="color:#75715e"&gt;--异常
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;102&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Execution Time: &lt;span style="color:#ae81ff"&gt;1035&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;802&lt;/span&gt; ms&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;通过索引访问10条pg_statistic数据，shared hit有100w，跟SQL的100w planning shared hit差不多。（注意这里的 Planning Time很少，说明我们没有在生成执行计划阶段出问题）&lt;/p&gt;

&lt;h3 class="relative group"&gt;索引dead tuple
 &lt;div id="索引dead-tuple" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%b4%a2%e5%bc%95dead-tuple" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;如果vacuum没有真的“跑起来”，那么索引的dead tuple还是会指向死元组
参考&lt;a href="https://blog.csdn.net/qq_40687433/article/details/137368881?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522172420012616800225589534%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&amp;amp;request_id=172420012616800225589534&amp;amp;biz_id=0&amp;amp;utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-2-137368881-null-null.nonecase&amp;amp;utm_term=%E8%86%A8%E8%83%80&amp;amp;spm=1018.2226.3001.4450" target="_blank" rel="noreferrer"&gt;从很慢的唯一索引扫描到索引膨胀&lt;/a&gt;



&lt;img src="https://lastdba.com/img/csdn/16f28ad1a331.png" alt="image.png" /&gt;&lt;/p&gt;

&lt;h3 class="relative group"&gt;autovacuum未回收死元组
 &lt;div id="autovacuum未回收死元组" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#autovacuum%e6%9c%aa%e5%9b%9e%e6%94%b6%e6%ad%bb%e5%85%83%e7%bb%84" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;表膨胀这么大，autovacuum不应该回收吗？&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;select * from pg_stat_all_tables where relname=&amp;#39;pg_statistic&amp;#39;\gx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-[ RECORD 1 ]-------+------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;relid | 2619
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;schemaname | pg_catalog
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;relname | pg_statistic
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;seq_scan | 1 	 --顺序访问pg_statistic极少
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;seq_tup_read | 4655
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;idx_scan | 28715508 --索引访问pg_statistic多
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;idx_tup_fetch | 25150245
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n_tup_ins | 46
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n_tup_upd | 1292143 --update很多
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n_tup_del | 14
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n_tup_hot_upd | 138448
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n_live_tup | 4655
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n_dead_tup | 1496776
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n_mod_since_analyze | 1292203
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n_ins_since_vacuum | 0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;last_vacuum | [null]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;last_autovacuum | 2024-08-16 20:34:15.045022+08 --注意autovacuum的时间是一个最近的值
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;last_analyze | [null]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;last_autoanalyze | [null]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;vacuum_count | 0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;autovacuum_count | 144170
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;analyze_count | 0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;autoanalyze_count | 0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;其实&lt;code&gt;pg_statistic&lt;/code&gt;上是autovacuum一直在跑，只不过进程有可能看不到，因为autovacuum没有跑什么，所以跑的比较快，跑完又snap休息了&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;show autovacuum_naptime ;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; autovacuum_naptime 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1min&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;每间隔1分钟休息一次，日志中也是每隔1分钟打印一次autovacuum信息。&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-08-16 21:05:15.267 CST,,,41080,,66bf4e87.a078,1,,2024-08-16 21:05:11 CST,27/166839,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;automatic vacuum of table &amp;#34;&amp;#34;lzldb.pg_catalog.pg_statistic&amp;#34;&amp;#34;: index scans: 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;pages: 0 removed, 132685 remain, 1 skipped due to pins, 0 skipped frozen
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;tuples: 0 removed, 1501745 remain, 1497090 are dead but not yet removable, oldest xmin: 119329380
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;buffer usage: 265443 hits, 0 misses, 0 dirtied
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;avg read rate: 0.000 MB/s, avg write rate: 0.000 MB/s
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;system usage: CPU: user: 0.53 s, system: 0.17 s, elapsed: 3.38 s
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;WAL usage: 1 records, 0 full page images, 233 bytes&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;autovacuum worker&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-08-16 21:05:17.474 CST,,,41080,,66bf4e87.a078,2,,2024-08-16 21:05:11 CST,27/166844,136438968,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;automatic analyze of table &amp;#34;&amp;#34;lzldb.public.lzlinfo&amp;#34;&amp;#34; system usage: CPU: user: 2.02 s, system: 0.00 s, elapsed: 2.08 s&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;autovacuum worker&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;1497090 are dead but not yet removable&lt;/code&gt;虽然触发了autovacuum但是根本没有回收到死元组，1497090条死元组没有清理。
排查下库内是谁持有了&lt;code&gt;oldest xmin: 119329380&lt;/code&gt;，很快可以定位到复制槽：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_replication_slots;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; slot_name &lt;span style="color:#f92672"&gt;|&lt;/span&gt; plugin &lt;span style="color:#f92672"&gt;|&lt;/span&gt; slot_type &lt;span style="color:#f92672"&gt;|&lt;/span&gt; datoid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;database&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;temporary&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active_pid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; xmin &lt;span style="color:#f92672"&gt;|&lt;/span&gt; catalog_xmin &lt;span style="color:#f92672"&gt;|&lt;/span&gt; restart_lsn &lt;span style="color:#f92672"&gt;|&lt;/span&gt; confirmed_flush_lsn &lt;span style="color:#f92672"&gt;|&lt;/span&gt; wal_status &lt;span style="color:#f92672"&gt;|&lt;/span&gt; safe_wal_size 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-----------------+----------+-----------+--------+----------+-----------+--------+------------+--------+--------------+--------------+---------------------+------------+---------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; slotslotlostname &lt;span style="color:#f92672"&gt;|&lt;/span&gt; pgoutput &lt;span style="color:#f92672"&gt;|&lt;/span&gt; logical &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;17076&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzldb &lt;span style="color:#f92672"&gt;|&lt;/span&gt; f &lt;span style="color:#f92672"&gt;|&lt;/span&gt; f &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;119329380&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;F9&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;105&lt;/span&gt;A4970 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;F9&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;105&lt;/span&gt;F8778 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; extended &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;slot的&lt;code&gt;catalog_xmin=119329380&lt;/code&gt;，与vacuum展示的&lt;code&gt;oldest xmin: 119329380&lt;/code&gt;一致。
&lt;code&gt;active=f&lt;/code&gt;说明复制链路已经挂了。&lt;/p&gt;

&lt;h3 class="relative group"&gt;修复问题
 &lt;div id="修复问题" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%bf%ae%e5%a4%8d%e9%97%ae%e9%a2%98" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;把复制槽删除：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; pg_drop_replication_slot(&lt;span style="color:#e6db74"&gt;&amp;#39;slotslotlostname&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pg_drop_replication_slot 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--------------------------&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;手动vacuum或再等待1分钟autovacuum。
最后再开一个全新的会话测试一下恢复没有：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;##&lt;/span&gt; psql
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;psql (&lt;span style="color:#ae81ff"&gt;13&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Type&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;help&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; help.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt; lzldb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;You &lt;span style="color:#66d9ef"&gt;are&lt;/span&gt; now connected &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;database&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;user&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;postgres&amp;#34;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt;,buffers,timing) &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzlinfo &lt;span style="color:#66d9ef"&gt;limit&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;---------------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Limit&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;71&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;023&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;025&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Seq Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzlinfo (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;3802&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;73&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;473&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;71&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;018&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;018&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2578&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning Time: &lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;605&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Execution Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;098&lt;/span&gt; ms&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;耗时从1s下降到10ms，Planning shared hit从100w下降到2k，问题基本解决。&lt;/p&gt;

&lt;h2 class="relative group"&gt;案例总结
 &lt;div id="案例总结" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%a1%88%e4%be%8b%e6%80%bb%e7%bb%93" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;复制链路挂掉，复制槽未及时清理，导致pg_statistic统计信息基表膨胀，导致每个backend在首次加载统计信息时都非常缓慢且读取多余的page到本地缓存，导致每个backend的缓存都大于正常水平（2g左右），多个backend导致最后的OOM。
其实问题很简单，只是过程比较曲折···简言之：基表pg_statistic膨胀导致执行计划生成阶段访问数据过大。元数据基表膨胀其实还有其他棘手的问题，有缘再见了。&lt;/p&gt;</content:encoded></item><item><title>ORDER BY limit 10比ORDER BY limit 100更慢</title><link>https://lastdba.com/2024/08/12/order-by-limit-10%E6%AF%94order-by-limit-100%E6%9B%B4%E6%85%A2/</link><pubDate>Mon, 12 Aug 2024 00:00:00 +0000</pubDate><guid>https://lastdba.com/2024/08/12/order-by-limit-10%E6%AF%94order-by-limit-100%E6%9B%B4%E6%85%A2/</guid><description>&lt;h2 class="relative group"&gt;问题分析
 &lt;div id="问题分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;pg数据库中执行sql时，ORDER BY limit 10比ORDER BY limit 100更慢&lt;/p&gt;

&lt;h3 class="relative group"&gt;执行计划分析
 &lt;div id="执行计划分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%89%a7%e8%a1%8c%e8%ae%a1%e5%88%92%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#f92672"&gt;*&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; cl.ITEM_DESC &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; tablelzl2 cl &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; item_name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;name&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;and&lt;/span&gt; cl.ITEM_NO&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;abcdefg&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AS&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;item&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tablelzl1 RI
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;WHERE&lt;/span&gt; RI.column1&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;AAAA&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; RI.column2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;applyno20231112&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ORDER&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;BY&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; RI.column3 &lt;span style="color:#66d9ef"&gt;DESC&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;limit&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Limit (cost=0.43..1522.66 rows=10 width=990)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Index Scan Backward using idx_tablelzl1_column3 on tablelzl1 ri (cost=0.43..158007.45 rows=1038 width=990)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (((column1)::text = &amp;#39;AAAA&amp;#39;::text) AND ((column2)::text = &amp;#39;applyno20231112&amp;#39;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SubPlan 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Index Scan using uk_tablelzl2_ii on tablelzl2 cl (cost=0.27..5.29 rows=1 width=18)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Index Cond: (((item_no)::text = &amp;#39;manualSign&amp;#39;::text) AND ((item_name)::text = (ri.manual_sign)::text))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;主表没有走到column2索引，而是走column3排序字段索引的Index Scan Backward，scan index的cost非常高，而最终的cost比较低，实际执行需要9s
如果把limit 10改成limit 100，执行计划正常：&lt;/p&gt;</description><content:encoded>
&lt;h2 class="relative group"&gt;问题分析
 &lt;div id="问题分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;pg数据库中执行sql时，ORDER BY limit 10比ORDER BY limit 100更慢&lt;/p&gt;

&lt;h3 class="relative group"&gt;执行计划分析
 &lt;div id="执行计划分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%89%a7%e8%a1%8c%e8%ae%a1%e5%88%92%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#f92672"&gt;*&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; cl.ITEM_DESC &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; tablelzl2 cl &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; item_name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;name&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;and&lt;/span&gt; cl.ITEM_NO&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;abcdefg&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AS&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;item&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tablelzl1 RI
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;WHERE&lt;/span&gt; RI.column1&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;AAAA&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; RI.column2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;applyno20231112&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ORDER&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;BY&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; RI.column3 &lt;span style="color:#66d9ef"&gt;DESC&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;limit&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Limit (cost=0.43..1522.66 rows=10 width=990)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Index Scan Backward using idx_tablelzl1_column3 on tablelzl1 ri (cost=0.43..158007.45 rows=1038 width=990)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (((column1)::text = &amp;#39;AAAA&amp;#39;::text) AND ((column2)::text = &amp;#39;applyno20231112&amp;#39;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SubPlan 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Index Scan using uk_tablelzl2_ii on tablelzl2 cl (cost=0.27..5.29 rows=1 width=18)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Index Cond: (((item_no)::text = &amp;#39;manualSign&amp;#39;::text) AND ((item_name)::text = (ri.manual_sign)::text))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;主表没有走到column2索引，而是走column3排序字段索引的Index Scan Backward，scan index的cost非常高，而最终的cost比较低，实际执行需要9s
如果把limit 10改成limit 100，执行计划正常：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#f92672"&gt;*&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; cl.ITEM_DESC &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; tablelzl2 cl &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; cl.ITEM_NAME &lt;span style="color:#f92672"&gt;=&lt;/span&gt; RI.MANUAL_SIGN &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; cl.ITEM_NO&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;manualSign&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AS&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;manualSign&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tablelzl1 RI
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;WHERE&lt;/span&gt; RI.column1&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;AAAA&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; RI.column2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;applyno20231112&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ORDER&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;BY&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; RI.column3 &lt;span style="color:#66d9ef"&gt;DESC&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;limit&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-----------------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Limit (cost=2632.28..3162.78 rows=100 width=990)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Result (cost=2632.28..8138.87 rows=1038 width=990)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Sort (cost=2632.28..2634.87 rows=1038 width=474)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Sort Key: ri.column3 DESC
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Index Scan using idx_cri_column2 on tablelzl1 ri (cost=0.43..2592.61 rows=1038 width=474)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Index Cond: ((column2)::text = &amp;#39;applyno20231112&amp;#39;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((column1)::text = &amp;#39;AAAA&amp;#39;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SubPlan 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Index Scan using uk_tablelzl2_ii on tablelzl2 cl (cost=0.27..5.29 rows=1 width=18)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Index Cond: (((item_no)::text = &amp;#39;manualSign&amp;#39;::text) AND ((item_name)::text = (ri.manual_sign)::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(10 rows)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;子查询执行计划不变，主表走到column2单列索引，回表后排序再limit，执行非常快。
不仅是limit，如果原sql仅更换column2的值，执行计划也正常。也就是说这个生产的sql只有极个别的column2的值时执行计划是异常的。&lt;/p&gt;
&lt;p&gt;执行计划分析：
子查询前后没变可以不用分析，主要是索引选择上的不同。column2是过滤字段，column3是排序字段，两个执行计划分别选择了这2个字段的索引。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;异常的limit 10执行计划：&lt;em&gt;反向扫描排序字段索引-&amp;gt;回表 -&amp;gt;limit&lt;/em&gt;。因为不需要额外排序，反向扫描索引时找到limit个数据就可以不用继续扫描了；扫描排序字段索引的预估代价非常高，最上层的limit最终代价预估很低。&lt;/li&gt;
&lt;li&gt;正常的limit 100执行计划：&lt;em&gt;访问过滤字段索引-&amp;gt;回表 -&amp;gt;以排序字段排序 -&amp;gt;limit&lt;/em&gt;。因为要排序，需要把符合条件的所有索引条目全部找出来；本身访问过滤字段的索引代价预估低。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以问题的关键在于&lt;em&gt;部分&lt;/em&gt;反向扫描排序索引时，代价预估的过低&lt;/p&gt;

&lt;h3 class="relative group"&gt;真实的执行情况
 &lt;div id="真实的执行情况" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%9c%9f%e5%ae%9e%e7%9a%84%e6%89%a7%e8%a1%8c%e6%83%85%e5%86%b5" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;explain (analyze,buffers) &lt;/code&gt;看下真实的执行情况&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Limit (cost=0.43..1521.93 rows=10 width=990) (actual time=23.311..8122.516 rows=10 loops=1)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit=861100 read=42985 dirtied=7
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; I/O Timings: read=6741.003
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Index Scan Backward using idx_tablelzl1_column3 on tablelzl1 ri (cost=0.43..157932.45 rows=1038 width=990) (actual time=23.309..8122.505 rows=10 loops=1)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (((column1)::text = &amp;#39;AAAA&amp;#39;::text) AND ((column2)::text = &amp;#39;applyno20231112&amp;#39;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Rows Removed by Filter: 1521796
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit=861100 read=42985 dirtied=7
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; I/O Timings: read=6741.003
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SubPlan 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Index Scan using uk_tablelzl2_ii on tablelzl2 cl (cost=0.27..5.29 rows=1 width=18) (actual time=0.005..0.005 rows=0 loops=10)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Index Cond: (((item_no)::text = &amp;#39;manualSign&amp;#39;::text) AND ((item_name)::text = (ri.manual_sign)::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit=6
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit=121 read=28
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; I/O Timings: read=1.476
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning Time: 2.314 ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Execution Time: 8122.658 ms&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Limit (cost=2632.28..3162.78 rows=100 width=990) (actual time=150.101..150.122 rows=14 loops=1)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit=700 read=274
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; I/O Timings: read=146.903
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Result (cost=2632.28..8138.87 rows=1038 width=990) (actual time=150.100..150.119 rows=14 loops=1)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit=700 read=274
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; I/O Timings: read=146.903
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Sort (cost=2632.28..2634.87 rows=1038 width=474) (actual time=150.072..150.073 rows=14 loops=1)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Sort Key: ri.column3 DESC
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Sort Method: quicksort Memory: 30kB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit=694 read=274
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; I/O Timings: read=146.903
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Index Scan using idx_cri_column2 on tablelzl1 ri (cost=0.43..2592.61 rows=1038 width=474) (actual time=0.418..149.973 rows=14 loops=1)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Index Cond: ((column2)::text = &amp;#39;applyno20231112&amp;#39;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((column1)::text = &amp;#39;AAAA&amp;#39;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Rows Removed by Filter: 1218
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit=691 read=274
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; I/O Timings: read=146.903
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SubPlan 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Index Scan using uk_tablelzl2_ii on tablelzl2 cl (cost=0.27..5.29 rows=1 width=18) (actual time=0.002..0.002 rows=0 loops=14)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Index Cond: (((item_no)::text = &amp;#39;manualSign&amp;#39;::text) AND ((item_name)::text = (ri.manual_sign)::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit=6
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning Time: 0.334 ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Execution Time: 150.257 ms&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;limit 10的执行计划，执行8s，内存读shared hit=861100 磁盘读read=42985 ，丢弃了1521796行
limit 100的执行计划执行0.1s shared hit=694 read=274，丢弃了1218行
limit 10的执行计划明显是不正常，&lt;strong&gt;读了太多的数据才找到符合条件的行&lt;/strong&gt;，这是sql执行过慢的原因&lt;/p&gt;

&lt;h3 class="relative group"&gt;统计信息分析
 &lt;div id="统计信息分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%bb%9f%e8%ae%a1%e4%bf%a1%e6%81%af%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;本身预估的代价不高，但是实际上需要扫描非常多的索引行，首先想到是否是统计信息是否准确
表的统计信息：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[postgres@cnsz381785:7169/(rasesql)phmamp][10-30.15:01:26]M=# select relpages,reltuples::bigint from pg_class where relname=&amp;#39;tablelzl1&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; relpages | reltuples 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------+-----------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 91172 | 2280874 --count出来差不多&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;字段的统计信息：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[phmampopr@cnsz381785:7169/(rasesql)phmamp][10-27.17:08:48]M=&amp;gt; select * from pg_stats where tablename=&amp;#39;tablelzl1&amp;#39; and attname=&amp;#39;column2&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-[ RECORD 1 ]----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;schemaname | public
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tablename | tablelzl1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;attname | column2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;inherited | f
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;null_frac | 0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;avg_width | 18
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n_distinct | -0.11990886
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;most_common_vals | {applyno20231112,DY20190723006650,DY20200102012899,DY20180827000557,DY20190524001304,DY20190529001885,DY20190728002359}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;most_common_freqs | {0.0005,0.00026666667,0.00023333334,0.0002,0.0002,0.0002,0.0002}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;histogram_bounds | {CULZF0000121605605,DSNEW0000126854232,DSNEW0000137652871,DY20160516001057,DY20161104005509,DY20170306002677,DY20170703010428,DY20170928013517,DY20180410007383,DY20180615002936,DY20180
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;correlation | 0.3131596
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;most_common_elems | [null]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;most_common_elem_freqs | [null]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;elem_count_histogram | [null]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这个column2 applyno20231112刚好就是排第一的most_common_vals，出现预估概率是0.0005，用预估的行2280874*0.0005=1140，与实际的行数1232差不多&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[postgres@cnsz381785:7169/(rasesql)phmamp][10-30.15:05:28]M=# select count(*) from tablelzl1 where column2 = &amp;#39;applyno20231112&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; count 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1232&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;说明统计信息是准确的，实际上运行&lt;code&gt;analze&lt;/code&gt;收集统计信息也不会解决这个问题&lt;/p&gt;

&lt;h2 class="relative group"&gt;数据分布不均的计算
 &lt;div id="数据分布不均的计算" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%95%b0%e6%8d%ae%e5%88%86%e5%b8%83%e4%b8%8d%e5%9d%87%e7%9a%84%e8%ae%a1%e7%ae%97" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;用当前统计信息计算出来的符合条件的行有1140个，那么预计从排序字段的索引上找到第一条数据平均要扫描2280874/1140=2000个索引行。如果找10条便是20000个索引行，100条便是200000个索引行。&lt;/p&gt;
&lt;p&gt;把sort禁用，让limit 100语句强行走排序字段的索引&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;M&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; enable_sort&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;off&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;SET&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--limit 100的执行计划
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Limit (cost=0.43..15222.69 rows=100 width=990)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Index Scan Backward using idx_tablelzl1_column3 on tablelzl1 ri (cost=0.43..158007.45 rows=1038 width=990)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (((column1)::text = &amp;#39;AAAA&amp;#39;::text) AND ((column2)::text = &amp;#39;applyno20231112&amp;#39;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SubPlan 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Index Scan using uk_tablelzl2_ii on tablelzl2 cl (cost=0.27..5.29 rows=1 width=18)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Index Cond: (((item_no)::text = &amp;#39;manualSign&amp;#39;::text) AND ((item_name)::text = (ri.manual_sign)::text))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;limit 10改成limit 100后的执行计划，代价从1522.66升到了15222.69，基本上只是简单的*10。limit 100的代价15222.69大于了走过滤字段索引的执行计划cost 3162.78，所以limit 10和limit 100执行计划不同，选择了不同的索引。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;以上的估算都是以数据零散的放在排序列的索引上 为前提的，实际情况有可能数据在最后一条（反向扫描索引），很快就能找到；也有可能数据全部在索引叶节点前面的几个pages，此时几乎是扫描全部索引并回表，代价便非常高。&lt;/strong&gt;
那么两个字段的关联度，数据在索引上的分布情况，决定了使用排序字段的索引 的效率。&lt;/p&gt;
&lt;p&gt;再看下真实的执行扫描了多少行数据：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Index Scan Backward using idx_tablelzl1_column3 on tablelzl1 ri (cost=0.43..157932.45 rows=1038 width=990) (actual time=23.309..8122.505 rows=10 loops=1)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (((column1)::text = &amp;#39;AAAA&amp;#39;::text) AND ((column2)::text = &amp;#39;applyno20231112&amp;#39;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Rows Removed by Filter: 1521796&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;实际上差不多扫描了1521796行才找到这10条数据，本来预估的是20000，整整相差了76倍！&lt;/p&gt;

&lt;h2 class="relative group"&gt;触发场景
 &lt;div id="触发场景" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%a7%a6%e5%8f%91%e5%9c%ba%e6%99%af" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;必须有where +order by+limit语句&lt;/li&gt;
&lt;li&gt;排序字段和过滤字段都必须有索引&lt;/li&gt;
&lt;li&gt;一般limit不会特别大&lt;/li&gt;
&lt;li&gt;数据分布不均&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;解决办法
 &lt;div id="解决办法" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%a7%a3%e5%86%b3%e5%8a%9e%e6%b3%95" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;改写sql语句：添加表达式，不让order by字段走索引即可&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#f92672"&gt;*&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; cl.ITEM_DESC &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; tablelzl2 cl &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; cl.ITEM_NAME &lt;span style="color:#f92672"&gt;=&lt;/span&gt; RI.MANUAL_SIGN &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; cl.ITEM_NO&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;manualSign&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AS&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;manualSign&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tablelzl1 RI
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;WHERE&lt;/span&gt; RI.column1&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;AAAA&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; RI.column2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;applyno20231112&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ORDER&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;BY&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; RI.column3 &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;DESC&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;limit&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 class="relative group"&gt;oracle是怎么做的
 &lt;div id="oracle是怎么做的" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#oracle%e6%98%af%e6%80%8e%e4%b9%88%e5%81%9a%e7%9a%84" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;执行计划cost的预估差异
 &lt;div id="执行计划cost的预估差异" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%89%a7%e8%a1%8c%e8%ae%a1%e5%88%92cost%e7%9a%84%e9%a2%84%e4%bc%b0%e5%b7%ae%e5%bc%82" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;从上面的执行计划分析，pg的执行计划cost看起来不太适应，上层的cost小于内层的cost，不像oracle这样阶梯式的累加计算
这里做一个oracle和pg的实验，一张表仅存储colname=&amp;lsquo;x&amp;rsquo;的数据，看下pg和oracle的对cost计算的区别：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[postgres@cnsz381785:7169/(rasesql)dbmgr][10-31.14:32:19]M=# explain select * from testlzl where col1=&amp;#39;x&amp;#39; limit 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-----------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Limit (cost=0.00..0.02 rows=1 width=2)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Seq Scan on testlzl (cost=0.00..17747.20 rows=1048576 width=2)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((col1)::text = &amp;#39;x&amp;#39;::text)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[postgres@cnsz381785:7169/(rasesql)dbmgr][10-31.14:32:30]M=# explain select * from testlzl where col1=&amp;#39;xx&amp;#39; limit 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-----------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Limit (cost=0.00..17747.20 rows=1 width=2)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Seq Scan on testlzl (cost=0.00..17747.20 rows=1 width=2)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((col1)::text = &amp;#39;xx&amp;#39;::text)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;col1=&amp;lsquo;x&amp;rsquo;立马就能找到，limit的算法没有推入到全表扫描的成本中，total cost是17747.20，跟扫描完表的成本是一样的。limit的成本cost虽然没有下推到内层的cost做计算，但是rows计算了！&lt;/p&gt;
&lt;p&gt;来看下oracle是执行计划是怎么做的：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SYS@t8icss1&amp;gt; select * from dbmgr.testlzl where a=&amp;#39;x&amp;#39; and rownum&amp;lt;=1;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;1 row selected.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Execution Plan
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Plan hash value: 2045386539
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| 0 | SELECT STATEMENT | | 1 | 2 | 2 (0)| 00:00:01 |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;|* 1 | COUNT STOPKEY | | | | | |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;|* 2 | TABLE ACCESS FULL| TESTLZL | 1 | 2 | 2 (0)| 00:00:01 |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Predicate Information (identified by operation id):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1 - filter(ROWNUM&amp;lt;=1)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2 - filter(&amp;#34;A&amp;#34;=&amp;#39;x&amp;#39;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SYS@t8icss1&amp;gt; select * from dbmgr.testlzl where a=&amp;#39;xx&amp;#39; and rownum&amp;lt;=1;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;no rows selected
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Execution Plan
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Plan hash value: 2045386539
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| 0 | SELECT STATEMENT | | 1 | 2 | 302 (2)| 00:00:01 |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;|* 1 | COUNT STOPKEY | | | | | |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;|* 2 | TABLE ACCESS FULL| TESTLZL | 1 | 2 | 302 (2)| 00:00:01 |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Predicate Information (identified by operation id):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1 - filter(ROWNUM&amp;lt;=1)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2 - filter(&amp;#34;A&amp;#34;=&amp;#39;xx&amp;#39;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;对于oracle的计划，a=&amp;lsquo;x&amp;rsquo;的数据可以立即找到的话，STOPKEY的代价算进了内层的cost中，cost只有2，实际上扫描全表的代价比较高302。&lt;/p&gt;
&lt;p&gt;这一点是oracle与pg关于cost计算的一个重要区别：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;oracle的外层cost必然&amp;gt;=内层cost；pg则不一定&lt;/li&gt;
&lt;li&gt;oracle的内层cost计算包含了外层的算子（比如stopkey）；但是pg不会包含，直接给子路径的全部成本&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;oracle的数据分布不均问题
 &lt;div id="oracle的数据分布不均问题" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#oracle%e7%9a%84%e6%95%b0%e6%8d%ae%e5%88%86%e5%b8%83%e4%b8%8d%e5%9d%87%e9%97%ae%e9%a2%98" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;知道了数据分布不均的原理，造一条数据把他放在排序索引的开头即可&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; tlzl(a char(&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;not&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;,b char(&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;not&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--插入批量数据
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;begin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;100000&lt;/span&gt; loop
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;insert&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;into&lt;/span&gt; tlzl &lt;span style="color:#66d9ef"&gt;values&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;test&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;test&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt; loop;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--插入特殊数据
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;insert&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;into&lt;/span&gt; tlzl &lt;span style="color:#66d9ef"&gt;values&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;aaaa&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;aaaa&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;insert&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;into&lt;/span&gt; tlzl &lt;span style="color:#66d9ef"&gt;values&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;zzzz&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;zzzz&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--创建索引
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; idx_a &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; tlzl(a);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; idx_b &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; tlzl(b);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--收集统计信息
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;EXEC&lt;/span&gt; DBMS_STATS.GATHER_TABLE_STATS(OWNNAME&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;SYS&amp;#39;&lt;/span&gt;,TABNAME&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;TLZL&amp;#39;&lt;/span&gt;,estimate_percent &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, degree&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,METHOD_OPT&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;FOR ALL COLUMNS SIZE AUTO&amp;#39;&lt;/span&gt;,&lt;span style="color:#66d9ef"&gt;cascade&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#75715e"&gt;/*+ index(tlzl idx_a)*/&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; tlzl &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; b&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;aaaa&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;order&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;by&lt;/span&gt; a) &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; rownum&lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#75715e"&gt;/*+ index(tlzl idx_a)*/&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; tlzl &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; b&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;zzzz&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;order&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;by&lt;/span&gt; a) &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; rownum&lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SYS@t8icss1&amp;gt; select * from (select /*+ index(tlzl idx_a)*/* from tlzl where b=&amp;#39;aaaa&amp;#39; order by a) where rownum&amp;lt;=1; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Execution Plan
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Plan hash value: 3674066029
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| 0 | SELECT STATEMENT | | 1 | 204 | 2210 (1)| 00:00:01 |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;|* 1 | COUNT STOPKEY | | | | | |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| 2 | VIEW | | 1 | 204 | 2210 (1)| 00:00:01 |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;|* 3 | TABLE ACCESS BY INDEX ROWID| TLZL | 1 | 202 | 2210 (1)| 00:00:01 |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| 4 | INDEX FULL SCAN | IDX_A | 98830 | | 779 (1)| 00:00:01 |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---------------------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SYS@t8icss1&amp;gt; select * from (select /*+ index(tlzl idx_a)*/* from tlzl where b=&amp;#39;zzzz&amp;#39; order by a) where rownum&amp;lt;=1; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Execution Plan
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Plan hash value: 3674066029
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| 0 | SELECT STATEMENT | | 1 | 204 | 2210 (1)| 00:00:01 |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;|* 1 | COUNT STOPKEY | | | | | |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| 2 | VIEW | | 1 | 204 | 2210 (1)| 00:00:01 |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;|* 3 | TABLE ACCESS BY INDEX ROWID| TLZL | 1 | 202 | 2210 (1)| 00:00:01 |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| 4 | INDEX FULL SCAN | IDX_A | 98830 | | 779 (1)| 00:00:01 |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---------------------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;oracle的优化器也是一样的，优化器并不知道数据到底放在索引的哪个地方，没有办法，放在索引的第一条和最后一条都是估算的同一代价。
不过oracle有很多方法可以解决这个问题，如extended statistic、Automatic Column Group Detection、固化执行计划等。&lt;/p&gt;

&lt;h2 class="relative group"&gt;参考
 &lt;div id="参考" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%8f%82%e8%80%83" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://www.postgres.cn/v2/news/viewone/1/717" target="_blank" rel="noreferrer"&gt;http://www.postgres.cn/v2/news/viewone/1/717&lt;/a&gt;
&lt;a href="https://oracle-base.com/articles/12c/automatic-column-group-detection-extended-statistics-12cr1" target="_blank" rel="noreferrer"&gt;https://oracle-base.com/articles/12c/automatic-column-group-detection-extended-statistics-12cr1&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>pg报错attempted to delete invisible tuple</title><link>https://lastdba.com/2024/08/12/pg%E6%8A%A5%E9%94%99attempted-to-delete-invisible-tuple/</link><pubDate>Mon, 12 Aug 2024 00:00:00 +0000</pubDate><guid>https://lastdba.com/2024/08/12/pg%E6%8A%A5%E9%94%99attempted-to-delete-invisible-tuple/</guid><description>&lt;h2 class="relative group"&gt;问题描述
 &lt;div id="问题描述" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e6%8f%8f%e8%bf%b0" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;postgresql数据库执行delete报错：&lt;code&gt;attempted to delete invisible tuple&lt;/code&gt;，执行同样条件的select不报错&lt;/p&gt;</description><content:encoded>
&lt;h2 class="relative group"&gt;问题描述
 &lt;div id="问题描述" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e6%8f%8f%e8%bf%b0" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;postgresql数据库执行delete报错：&lt;code&gt;attempted to delete invisible tuple&lt;/code&gt;，执行同样条件的select不报错&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;delete&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzltab1;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzltab1;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;执行全表删除和全表查询的结果：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;M&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;delete&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzltab1;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ERROR: &lt;span style="color:#ae81ff"&gt;55000&lt;/span&gt;: attempted &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;delete&lt;/span&gt; invisible tuple
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;LOCATION&lt;/span&gt;: heap_delete, heapam.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;2500&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Time: &lt;span style="color:#ae81ff"&gt;511&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;050&lt;/span&gt; ms&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;M&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzltab1;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;231187&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;delete找到了不可见的元组，select却是正常的 。
当时觉得很奇怪。pg的可见性通过元组的xmin,xmax,cid和快照的xmin，xmax，xip_list判断的，虽然delete元组的事务状态和时间会对可见性产生影响，但是表数据如果稳定（当前没有任何dml操作的话），随后的任何快照进去拍摄，都应该是一个稳定的可见集，它并不存在当前事务可见性判断，dml事务元组可见性判断也应该一致。也就是说这种场景下，select快照和delete快照不应该有这种差异。&lt;/p&gt;

&lt;h2 class="relative group"&gt;问题分析
 &lt;div id="问题分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;找到源码
 &lt;div id="找到源码" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%89%be%e5%88%b0%e6%ba%90%e7%a0%81" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;注意报错信息&lt;code&gt;heapam.c:2500&lt;/code&gt;
找到源码位置&lt;code&gt;src/backend/access/heap/heapam.c&lt;/code&gt;
2500的行是空的，附近的代码如下&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * Before locking the buffer, pin the visibility map page if it appears to
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * be necessary. Since we haven&amp;#39;t got the lock yet, someone else might be
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * in the middle of changing this, so we&amp;#39;ll need to recheck after we have
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * the lock.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;PageIsAllVisible&lt;/span&gt;(page))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;visibilitymap_pin&lt;/span&gt;(relation, block, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;vmbuffer);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;LockBuffer&lt;/span&gt;(buffer, BUFFER_LOCK_EXCLUSIVE);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;从源码看，它在尝试获得vm上的锁，看来问题跟vm文件相关。&lt;/p&gt;

&lt;h3 class="relative group"&gt;vm文件
 &lt;div id="vm文件" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#vm%e6%96%87%e4%bb%b6" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;什么是vm文件？&lt;/strong&gt;
vm文件是为了减少vacuum扫描page时间的，如果一个page不需要vacuum那么它应该可以被vacuum跳过，这样可以大大减少vacuum寻找需要清理的page的时间，这是vm文件最初的目的。（有时候也会被index-only scan使用，不过我们这里不会涉及，我们用的是全表扫描）
vm文件包含两个信息：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;page中的元组是不是都是可见的。说明page中没有需要被vacuum的死元组&lt;/li&gt;
&lt;li&gt;page中的元组是不是都是冻结的。说明vacuum freeze不需要访问这个page&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/1604296b876a.png" alt="Fig. 6.2. How the VM is used." /&gt;&lt;/p&gt;
&lt;p&gt;vm会帮助vacuum寻找死元组，减少扫描的页的数量。比如上面这个图（interdb yyds！），第一个页面1st不包含死元组，那么vacuum就可以跳过这个页面。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;找到vm文件&lt;/strong&gt;
每个表都有Visibility Map (VM)（索引没有vm文件），单独存放在表文件的旁边，如果一个表的filenode为&lt;code&gt;12345&lt;/code&gt;，那么vm文件应该是&lt;code&gt;12345_vm&lt;/code&gt;
首先cd到data目录&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;M&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#75715e"&gt;# show data_directory;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; data_directory 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; /pg/pg6666/data&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;通过database oid，表的oid可以找到文件存储的位置&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; oid,datname &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_database &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; datname&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;sdp&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-------+----------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; oid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; datname
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;17075&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; sdp
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; oid,relname &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_class &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; relname&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;lzltab1&amp;#39;&lt;/span&gt;; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-------+----------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;17362&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzltab1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; pg_relation_filepath(&lt;span style="color:#e6db74"&gt;&amp;#39;lzltab1&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pg_relation_filepath 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;----------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;base&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;17075&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;17362&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;找到数据文件和vm&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ cd /pg/pg6666/data/base/17075
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ ll 17362*
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;86761472&lt;/span&gt; Jun &lt;span style="color:#ae81ff"&gt;15&lt;/span&gt; 17:43 &lt;span style="color:#ae81ff"&gt;17362&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;40960&lt;/span&gt; Jun &lt;span style="color:#ae81ff"&gt;9&lt;/span&gt; 21:09 17362_fsm
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;8192&lt;/span&gt; Nov &lt;span style="color:#ae81ff"&gt;14&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2022&lt;/span&gt; 17362_vm&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 class="relative group"&gt;pg_visibility插件
 &lt;div id="pg_visibility插件" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#pg_visibility%e6%8f%92%e4%bb%b6" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;pg_visibility提供通过检查vm文件输出页级别的可见性信息，而且可以检测vm是否损坏。因为vm存储了“&lt;em&gt;page中的元组是不是都是可见的；page中的元组是不是都是冻结的&lt;/em&gt;”这些信息，pg_visibility可以检查出哪些页是all-frozen的，哪些是all-visible的。
pg_visibility插件使用参考：&lt;a href="https://www.postgresql.org/docs/current/pgvisibility.html" target="_blank" rel="noreferrer"&gt;https://www.postgresql.org/docs/current/pgvisibility.html&lt;/a&gt;&lt;/p&gt;

&lt;h4 class="relative group"&gt;会用到的pg_visibility中的function
 &lt;div id="会用到的pg_visibility中的function" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%bc%9a%e7%94%a8%e5%88%b0%e7%9a%84pg_visibility%e4%b8%ad%e7%9a%84function" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;pg_visibility_map_summary()&lt;/strong&gt;：显示vm中的all-visible页和all-frozen页
&lt;strong&gt;pg_check_frozen()&lt;/strong&gt;：有元组不是frozen的，但在它所在的页在vm中被标记为了all-frozen，如果该函数有返回，表示vm文件损坏。
&lt;strong&gt;pg_check_visible()&lt;/strong&gt;：有元组不是visible的，但在它所在的页在vm中被标记为了all-visible，如果该函数有返回，表示vm文件损坏。
&lt;strong&gt;pg_truncate_visibility_map()&lt;/strong&gt;：清理vm文件。清理vm后，当表首次执行vacuum时，会扫描表上的所有页并重建vm。&lt;/p&gt;

&lt;h3 class="relative group"&gt;修复vm文件
 &lt;div id="修复vm文件" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%bf%ae%e5%a4%8dvm%e6%96%87%e4%bb%b6" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;检查vm是否损坏&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;M&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; pg_visibility_map_summary(&lt;span style="color:#e6db74"&gt;&amp;#39;lzltab1&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pg_visibility_map_summary 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;---------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;472&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;all-visible 472页，all-frozen 0页&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;M&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; pg_check_frozen(&lt;span style="color:#e6db74"&gt;&amp;#39;lzltab1&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pg_check_frozen 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-----------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;M&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; pg_check_visible(&lt;span style="color:#e6db74"&gt;&amp;#39;lzltab1&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pg_check_visible 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;6839&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;6839&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;7296&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;1423&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;pg_check_visible()有结果说明&lt;strong&gt;vm已经损坏了&lt;/strong&gt;
然后用pg_truncate_visibility_map()执行清空vm&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;M&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; pg_truncate_visibility_map(&lt;span style="color:#e6db74"&gt;&amp;#39;lzltab1&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pg_truncate_visibility_map 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;----------------------------&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;从磁盘上也能看出来vm被清空了&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ll 17362*
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;86761472&lt;/span&gt; Jun &lt;span style="color:#ae81ff"&gt;27&lt;/span&gt; 10:39 &lt;span style="color:#ae81ff"&gt;17362&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;40960&lt;/span&gt; Jun &lt;span style="color:#ae81ff"&gt;9&lt;/span&gt; 21:09 17362_fsm
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; Jun &lt;span style="color:#ae81ff"&gt;27&lt;/span&gt; 18:18 17362_vm&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;然后我们验证一下，vacuum表看下是否会生产vm文件，并检验vm文件是否没有损坏&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;M&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;vacuum&lt;/span&gt; lzltab1;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;VACUUM&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Time: &lt;span style="color:#ae81ff"&gt;3692&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;402&lt;/span&gt; ms (&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;03&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;692&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;M&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;q
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt; ll &lt;span style="color:#ae81ff"&gt;17362&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;rw&lt;span style="color:#75715e"&gt;------- 1 postgres postgres 86761472 Jun 28 03:37 17362
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;rw&lt;span style="color:#75715e"&gt;------- 1 postgres postgres 40960 Jun 9 21:09 17362_fsm
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;rw&lt;span style="color:#75715e"&gt;------- 1 postgres postgres 8192 Jun 28 10:21 17362_vm&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;可以看到手动vacuum后vm正常生成&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;M&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; pg_check_visible(&lt;span style="color:#e6db74"&gt;&amp;#39;lzltab1&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pg_check_visible 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;M&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; pg_check_frozen(&lt;span style="color:#e6db74"&gt;&amp;#39;lzltab1&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pg_check_frozen 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-----------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;check检查后没有输出，vm文件正常，修复完成。&lt;/p&gt;
&lt;p&gt;最后再来跑下sql&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;##&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;delete&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzltab1;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;DELETE&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;229766&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;delete执行正常，问题解决&lt;/p&gt;

&lt;h3 class="relative group"&gt;检查全库是否有vm损坏
 &lt;div id="检查全库是否有vm损坏" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%a3%80%e6%9f%a5%e5%85%a8%e5%ba%93%e6%98%af%e5%90%a6%e6%9c%89vm%e6%8d%9f%e5%9d%8f" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;虽然我们解决了一个vm文件损坏的问题，但是仍然需要全库检查是否有其他的vm损坏（前提是安装了extension pg_visibility)&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; oid::regclass &lt;span style="color:#66d9ef"&gt;AS&lt;/span&gt; relname
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; pg_class
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;WHERE&lt;/span&gt; relkind &lt;span style="color:#66d9ef"&gt;IN&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;m&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;t&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;EXISTS&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; pg_check_visible(oid))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;OR&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;EXISTS&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; pg_check_frozen(oid)));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;如果返回非空结果，说明有vm损坏了。就像上面的方法，用pg_truncate_visibility_map()清理vm，然后vacuum生成一个vm。
如果是9.6前的版本，因为没有pg_visibility插件，需要停库然后手动删除vm文件，再启动数据库，然后再vacuum生成一个vm。&lt;/p&gt;

&lt;h2 class="relative group"&gt;为什么vm会损坏？
 &lt;div id="为什么vm会损坏" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%b8%ba%e4%bb%80%e4%b9%88vm%e4%bc%9a%e6%8d%9f%e5%9d%8f" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;我们通过一步步分析，检查到是vm文件损坏了，但是vm为什么会损坏呢？&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;pg数据库的bug。pg确实有些bug会导致vm损坏（参考wiki Visibility Map Problems），不过这些都是pg9.6.1以前的&lt;/li&gt;
&lt;li&gt;操作系统和硬件问题&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;我们版本是pg13的，问题基本只能笼统地归于操作系统或者硬件问题。&lt;/p&gt;

&lt;h2 class="relative group"&gt;为什么select没有问题，delete报错？
 &lt;div id="为什么select没有问题delete报错" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%b8%ba%e4%bb%80%e4%b9%88select%e6%b2%a1%e6%9c%89%e9%97%ae%e9%a2%98delete%e6%8a%a5%e9%94%99" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;select全表正常，delete全表报错，看上去就很奇怪。问题的根因是vm文件的损坏。
就像前面说的，vm文件是为了加快vacuum效率的，我们虽然没有做vacuum，而vm文件总要更新的吧？dml每次都会去更新vm（至少要检查），而select不会改变vm状态的。所以本案例中select正常执行，delete在执行到vm的处理时报错。
我们的案例中，delete扫描了vm找到了all-visible的页，但是vm标记错了，这些页上仍然有不可见的元组，这里就对应了开头的报错&lt;code&gt;attempted to delete invisible tuple&lt;/code&gt;。不可见的元组可能已经被delete了，再次跑delete当然会报错，这也违背了事务的可见性规则。
另外，如果是index-only-scan也会用到vm文件，所以也会影响select语句，不过这个案例是全表扫描的，所以select没有问题。&lt;/p&gt;

&lt;h2 class="relative group"&gt;vm损坏导致index-only-scan出现错误的数据结果
 &lt;div id="vm损坏导致index-only-scan出现错误的数据结果" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#vm%e6%8d%9f%e5%9d%8f%e5%af%bc%e8%87%b4index-only-scan%e5%87%ba%e7%8e%b0%e9%94%99%e8%af%af%e7%9a%84%e6%95%b0%e6%8d%ae%e7%bb%93%e6%9e%9c" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;前面在介绍vm的时候提到处理vacuum外，index-only-scan也会用到vm文件，虽然我们这个案例没有涉及index-only-scan，但本着研究透彻的原则，把问题搞清楚。&lt;/p&gt;

&lt;h3 class="relative group"&gt;什么是index-only-scan
 &lt;div id="什么是index-only-scan" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%bb%80%e4%b9%88%e6%98%afindex-only-scan" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;index-only-scan顾名思义就是仅索引扫描。在访问数据的时候不需要访问表，而只访问索引结构就能得到想要的结果。几乎所有的关系型数据库都有仅索引扫描，因为B+树索引结构保存了键值，如果查询只查了键值，那么仅索引扫描就是可能的。
但是，postgresql因为其事务实现跟其他数据库（Oracle、mysql）有很大的不同，它的仅索引扫描index-only-scan有一些特殊性。
postgresql通过元组头部的xmin、xmax等信息，校验元组和事务的可见性，而索引上没有这些信息，所以就导致pg的仅索引扫描必须访问数据块来检查可见性。这个时候vm的作用就体现了出来，因为vm文件中保存了all-visible，all-frozen的信息，这些被标记的页其实不需要校验元组可见性，因为他们已经被vm标记为可见了。



&lt;img src="https://lastdba.com/img/csdn/63ed5a39f52d.png" alt="Fig. 7.7. How Index-Only Scans performs" /&gt;
再来一个interdb的图（interdb yyds！）。当一个sql查询在访问key是18和19两个元组时，key=18元组所在的页已经被vm标记为all-visible了，所以访问key=18的元组只需要访问索引页和vm文件；而key=19的元组所在的页没有被标记为all-visible，仅索引扫描还是要访问所在数据页获取元组可见信息。&lt;/p&gt;

&lt;h3 class="relative group"&gt;index-only-scan查询出错误的结果
 &lt;div id="index-only-scan查询出错误的结果" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#index-only-scan%e6%9f%a5%e8%af%a2%e5%87%ba%e9%94%99%e8%af%af%e7%9a%84%e7%bb%93%e6%9e%9c" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;因为index-only-scan要访问vm，而vm损坏而保存了错误的信息，比如页中的元组本来不是所有都可见的（比如几个元组被delete了），但是页还是在vm中被标记为all-visible，导致index-only-scan没有进数据页检测元组可见性，直接返回了索引页上的本来是不可见的键值。
可以设置&lt;code&gt;enable_indexonlyscan=off&lt;/code&gt;来关闭index-only-scan特性，保证数据的正确性；当然也可以像上面那样去修复vm文件，也许是更好的选择。&lt;/p&gt;

&lt;h2 class="relative group"&gt;总结
 &lt;div id="总结" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%80%bb%e7%bb%93" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;虽然刚开始有些曲折，一看报错以为是事务可见性规则出现了问题，这个有问题的话问题就有点大了，但是实际上要简单的多。
我们从报错&lt;code&gt;attempted to delete invisible tuple&lt;/code&gt;分析到源码，并定位到了是vm问题，再通过pg_visibility插件检测出vm corrupt并修复了vm文件，从而解决了delete报错，最后扩展了一下index-only-scan和vm。
总结一下文章的知识点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pg_visibility插件可以读取、检测、清理vm文件&lt;/li&gt;
&lt;li&gt;如果没有vm信息的话，vacuum会生成新的vm&lt;/li&gt;
&lt;li&gt;dml会读取/更新vm文件，select不会（非index-only-scan）&lt;/li&gt;
&lt;li&gt;vm文件是为了提升vacuum的效率，有时候也会提升index-only-scan的效率&lt;/li&gt;
&lt;li&gt;&lt;code&gt;attempted to delete invisible tuple&lt;/code&gt;报错应该检查vm文件是否损坏&lt;/li&gt;
&lt;li&gt;vm文件损坏会造成dml失败，也会造成index-only-scan查询出错误的结果&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;参考
 &lt;div id="参考" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%8f%82%e8%80%83" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.postgresql.org/docs/13/pgvisibility.html" target="_blank" rel="noreferrer"&gt;https://www.postgresql.org/docs/13/pgvisibility.html&lt;/a&gt;
&lt;a href="https://wiki.postgresql.org/wiki/Visibility_Map_Problems" target="_blank" rel="noreferrer"&gt;https://wiki.postgresql.org/wiki/Visibility_Map_Problems&lt;/a&gt;
&lt;a href="https://www.interdb.jp/pg/pgsql06.html" target="_blank" rel="noreferrer"&gt;https://www.interdb.jp/pg/pgsql06.html&lt;/a&gt;
&lt;a href="https://www.interdb.jp/pg/pgsql07.html" target="_blank" rel="noreferrer"&gt;https://www.interdb.jp/pg/pgsql07.html&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>案例-insert value偶发慢分析</title><link>https://lastdba.com/2024/08/12/%E6%A1%88%E4%BE%8B-insert-value%E5%81%B6%E5%8F%91%E6%85%A2%E5%88%86%E6%9E%90/</link><pubDate>Mon, 12 Aug 2024 00:00:00 +0000</pubDate><guid>https://lastdba.com/2024/08/12/%E6%A1%88%E4%BE%8B-insert-value%E5%81%B6%E5%8F%91%E6%85%A2%E5%88%86%E6%9E%90/</guid><description>&lt;p&gt;业务insert value偶发变慢，当我去查看活动会话的时候写入慢问题已经缓解了。
后来发现写入慢问题持续不到半分钟，insert value写入时间1-2s，写个抓活动会话的脚本还是能拿到会话信息：&lt;/p&gt;</description><content:encoded>&lt;p&gt;业务insert value偶发变慢，当我去查看活动会话的时候写入慢问题已经缓解了。
后来发现写入慢问题持续不到半分钟，insert value写入时间1-2s，写个抓活动会话的脚本还是能拿到会话信息：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; wait_event &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;---------------------+-------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;] &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; WALRead &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; DataFileRead &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; BgWriterMain &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; WALWrite &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;40&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; AutoVacuumMain &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ClientRead &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;385&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; LogicalLauncherMain &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;等待事件最异常的就是WALWrite 40个会话。
其中2个WALWrite等待的会话如下：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; usename &lt;span style="color:#f92672"&gt;|&lt;/span&gt; xact_start &lt;span style="color:#f92672"&gt;|&lt;/span&gt; state_change &lt;span style="color:#f92672"&gt;|&lt;/span&gt; wait_event &lt;span style="color:#f92672"&gt;|&lt;/span&gt; wait_event_type &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; partofquery
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-------+----------+-------------------------------+-------------------------------+---------------+-----------------+--------+--------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;144955&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzluser11 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;07&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;58&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;516574&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;07&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;58&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;516588&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; WALWrite &lt;span style="color:#f92672"&gt;|&lt;/span&gt; LWLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;insert&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;into&lt;/span&gt; table1( 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;179869&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzluser11 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;07&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;58&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;28&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;116371&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;07&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;58&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;28&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;116386&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; WALWrite &lt;span style="color:#f92672"&gt;|&lt;/span&gt; IO &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;insert&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;into&lt;/span&gt; table1( &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;直接搜源码关于WALWrite的相关内容&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; WALWriteLock: must be held to write WAL buffers to &lt;span style="color:#a6e22e"&gt;disk&lt;/span&gt; (XLogWrite or
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; XLogFlush).&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;* LWLockAcquireOrWait - Acquire lock, or wait until it&amp;#39;s free
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;* The semantics of this function are a bit funky. If the lock is currently
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;* free, it is acquired in the given mode, and the function returns true. If
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;* the lock isn&amp;#39;t immediately free, the function waits until it is released
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;* and returns false, but does not acquire the lock.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;* This is currently used for WALWriteLock: when a backend flushes the WAL,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;* holding WALWriteLock, it can flush the commit records of many other
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;* backends as a side-effect. Those other backends need to wait until the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;* flush finishes, but don&amp;#39;t need to acquire the lock anymore. They can just
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;* wake up, observe that their records have already been flushed, and return.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;*/&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;wal从wal buffer写入磁盘时，必须持有WALWriteLock。
当backend刷wal时，持有WALWriteLock，它也能刷其他backends提交记录。其他backends需要等这个flush完成，但不需要再去持有锁了。如果他们的wal被刷了，他们能直接返回（而不是再去刷一次wal）。&lt;/p&gt;
&lt;p&gt;XLogFlush极其重要， XLogFlush的关键代码在for循环里：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Ensure that all XLOG data through the given position is flushed to disk.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * NOTE: this differs from XLogWrite mainly in that the WALWriteLock is not
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * already held, and we try to avoid acquiring it if possible.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;XLogFlush&lt;/span&gt;(XLogRecPtr record)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * Now wait until we get the write lock, or someone else does the flush
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * for us.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (;;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		XLogRecPtr	insertpos;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* read LogwrtResult and update local state */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;SpinLockAcquire&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;XLogCtl&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;info_lck);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (WriteRqstPtr &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; XLogCtl&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;LogwrtRqst.Write)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			WriteRqstPtr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; XLogCtl&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;LogwrtRqst.Write;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		LogwrtResult &lt;span style="color:#f92672"&gt;=&lt;/span&gt; XLogCtl&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;LogwrtResult;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;SpinLockRelease&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;XLogCtl&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;info_lck);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* done already? */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (record &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; LogwrtResult.Flush)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * Before actually performing the write, wait for all in-flight
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * insertions to the pages we&amp;#39;re about to write to finish.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		insertpos &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;WaitXLogInsertionsToFinish&lt;/span&gt;(WriteRqstPtr);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * Try to get the write lock. If we can&amp;#39;t get it immediately, wait
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * until it&amp;#39;s released, and recheck if we still need to do the flush
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * or if the backend that held the lock did it for us already. This
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * helps to maintain a good rate of group committing when the system
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * is bottlenecked by the speed of fsyncing.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;LWLockAcquireOrWait&lt;/span&gt;(WALWriteLock, LW_EXCLUSIVE))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * The lock is now free, but we didn&amp;#39;t acquire it yet. Before we
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * do, loop back to check if someone else flushed the record for
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * us already.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;continue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* Got the lock; recheck whether request is satisfied */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		LogwrtResult &lt;span style="color:#f92672"&gt;=&lt;/span&gt; XLogCtl&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;LogwrtResult;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (record &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; LogwrtResult.Flush)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;LWLockRelease&lt;/span&gt;(WALWriteLock);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * Sleep before flush! By adding a delay here, we may give further
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * backends the opportunity to join the backlog of group commit
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * followers; this can significantly improve transaction throughput,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * at the risk of increasing transaction latency.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * We do not sleep if enableFsync is not turned on, nor if there are
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * fewer than CommitSiblings other backends with active transactions.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (CommitDelay &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; enableFsync &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;MinimumActiveBackends&lt;/span&gt;(CommitSiblings))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;pg_usleep&lt;/span&gt;(CommitDelay);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * Re-check how far we can now flush the WAL. It&amp;#39;s generally not
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * safe to call WaitXLogInsertionsToFinish while holding
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * WALWriteLock, because an in-progress insertion might need to
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * also grab WALWriteLock to make progress. But we know that all
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * the insertions up to insertpos have already finished, because
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * that&amp;#39;s what the earlier WaitXLogInsertionsToFinish() returned.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * We&amp;#39;re only calling it again to allow insertpos to be moved
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * further forward, not to actually wait for anyone.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			insertpos &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;WaitXLogInsertionsToFinish&lt;/span&gt;(insertpos);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* try to write/flush later additions to XLOG as well */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		WriteRqst.Write &lt;span style="color:#f92672"&gt;=&lt;/span&gt; insertpos;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		WriteRqst.Flush &lt;span style="color:#f92672"&gt;=&lt;/span&gt; insertpos;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;XLogWrite&lt;/span&gt;(WriteRqst, false);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;LWLockRelease&lt;/span&gt;(WALWriteLock);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* done */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;XLogFlush函数是刷脏WAL的主要函数：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;判断需要flush的脏WAL是否已经被其他人flush了，如是，则直接返回&lt;/li&gt;
&lt;li&gt;尝试以排他模式获得锁WALWriteLock，不断尝试，直到获得锁为止&lt;/li&gt;
&lt;li&gt;拿到锁了，再次检查需要flush的脏WAL是否已经被其他人flush了，如是，则释放WALWriteLock，然后返回（申请锁期间也有可能脏WAL被其他人flush，如果是当然什么也不用做）&lt;/li&gt;
&lt;li&gt;等待commit_delay毫秒且并发提交事务数大于commit_siblings，更新wal的写入点，形成组提交 。这一步目前走不到，因为CommitDelay默认为0，相当于没有打开组提交&lt;/li&gt;
&lt;li&gt;调用XLogWrite写日志，写完释放WALWriteLock&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;XLogFlush刷脏wal需要判断当前请求的脏wal是不是已经写了，如果没写，会持有WALWriteLock直到XLogWrite函数日志写入完成。XLogWrite是写wal的具体函数，如写如到哪个page的哪个位置。&lt;/p&gt;
&lt;p&gt;回到之前活动会话的等待事件上。IO:WALWrite等待IO比较好理解，LWLOCK:WALWrite怎么去确认是不是问题呢？
从XLogFlush函数逻辑可知，WALWriteLock是pg在写脏wal时申请的排他LWlock（这很好理解，wal的提交信息是顺序写的，只能给排他模式写，不能谁写的快就谁写，不然数据容易出错），是串行的写wal提交信息。
了解这部分逻辑再回去看pg_stat_activity，会发现IO:WALWrite&lt;strong&gt;只有1个&lt;/strong&gt;，而LWLOCK:WALWrite有几十个。
虽然不能直接看到LWLOCK的blocking chain，但是我们可以从源码中得知，&lt;strong&gt;LWLOCK:WALWrite在等待IO:WALWrite&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.postgresql.org/docs/16/wal-configuration.html" target="_blank" rel="noreferrer"&gt;官方文档&lt;/a&gt;有一段关于XLogFlush和调整wal buffer的描述：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Normally, WAL buffers should be written and flushed by an XLogFlush request, which is made, for the most part, at transaction commit time to ensure that transaction records are flushed to permanent storage. On systems with high WAL output, XLogFlush requests might not occur often enough to prevent XLogInsertRecord from having to do writes. On such systems one should increase the number of WAL buffers by modifying the wal_buffers parameter. When full_page_writes is set and the system is very busy, setting wal_buffers higher will help smooth response times during the period immediately following each checkpoint.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;正常情况下，wal buffer会被XLogFlush flush，例如事务提交写wal日志到磁盘上。如果wal日志量很大，但是XLogFlush触发不频繁（也就是全是大事务），就需要XLogInsertRecord写没有提交的wal record，也就是说wal_buffer不够用了，此时增大wal_buffer会稍微对系统的响应时间有帮助。&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;There are two commonly used internal WAL functions: XLogInsertRecord and XLogFlush. XLogInsertRecord is used to place a new record into the WAL buffers in shared memory. If there is no space for the new record, XLogInsertRecord will have to write (move to kernel cache) a few filled WAL buffers&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;结合XLogInsertRecord函数的一段描述:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	 &lt;span style="color:#f92672"&gt;*&lt;/span&gt; We have now done all the preparatory work we can without holding a
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	 &lt;span style="color:#f92672"&gt;*&lt;/span&gt; lock or modifying shared state. From here on, inserting the new WAL
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	 &lt;span style="color:#f92672"&gt;*&lt;/span&gt; record to the shared WAL buffer cache is a two&lt;span style="color:#f92672"&gt;-&lt;/span&gt;step process:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	 &lt;span style="color:#f92672"&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	 &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1.&lt;/span&gt; Reserve the right amount of space from the WAL. The current head of
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	 &lt;span style="color:#f92672"&gt;*&lt;/span&gt;	 reserved space is kept in Insert&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;CurrBytePos, and is protected by
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	 &lt;span style="color:#f92672"&gt;*&lt;/span&gt;	 insertpos_lck.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	 &lt;span style="color:#f92672"&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	 &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2.&lt;/span&gt; Copy the record to the reserved WAL space. This involves finding the
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	 &lt;span style="color:#f92672"&gt;*&lt;/span&gt;	 correct WAL buffer containing the reserved space, and copying the
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	 &lt;span style="color:#f92672"&gt;*&lt;/span&gt;	 record in place. This can be done concurrently in multiple processes.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;XLogInsertRecord函数是用来将新的wal record到WAL buffer中的。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;写入需要保留一定量的空间&lt;/li&gt;
&lt;li&gt;拷贝wal record到保留的wal空间（应指的是wal buffer中的保留空间）。&lt;strong&gt;多个进程可并行执行&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;wal record拷贝到wal buffer是可以并行执行的。这很难称为瓶颈，因为是内存拷贝还有并行。
而XLogFlush函数就不是了，XLogFlush写入的时候会一直持有一个排他LWlock。所以，在这种并发高的小事务场景中，提高wal buffer理论上效果不会太理想。&lt;/p&gt;
&lt;p&gt;至此，可以排除wal_buffers内存调整，把关注点放在IO上。再看pg_stat_activity的IO类相关等待个数：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;DataFileRead	&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;DataFileExtend	&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WALWrite		&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WALRead			&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;insert value慢只持续了不到1分钟时间，平时没有异常。但是从平时的会话信息上看IO类的WALWrite等待基本都在&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; usename &lt;span style="color:#f92672"&gt;|&lt;/span&gt; xact_start &lt;span style="color:#f92672"&gt;|&lt;/span&gt; state_change &lt;span style="color:#f92672"&gt;|&lt;/span&gt; wait_event &lt;span style="color:#f92672"&gt;|&lt;/span&gt; wait_event_type &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; partofquery
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-------+----------+-------------------------------+-------------------------------+---------------+-----------------+--------+--------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;72668&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzluser11 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;828394&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;82841&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; WALWrite &lt;span style="color:#f92672"&gt;|&lt;/span&gt; IO &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;insert&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;into&lt;/span&gt; table1( &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;77215&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzluser11 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;33&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;342541&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;33&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;342552&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; WALWrite &lt;span style="color:#f92672"&gt;|&lt;/span&gt; IO &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;insert&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;into&lt;/span&gt; table1 &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;94904&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzluser11 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;34&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;442309&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;34&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;442323&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; WALWrite &lt;span style="color:#f92672"&gt;|&lt;/span&gt; IO &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;insert&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;into&lt;/span&gt; table1 &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;88024&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzluser11 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;36&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;28&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;779086&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;36&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;28&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;779311&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; WALWrite &lt;span style="color:#f92672"&gt;|&lt;/span&gt; IO &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;UPDATE&lt;/span&gt; table2 &lt;span style="color:#66d9ef"&gt;SET&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;103236&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzluser11 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;37&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;144283&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;37&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;144302&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; WALWrite &lt;span style="color:#f92672"&gt;|&lt;/span&gt; IO &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;insert&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;into&lt;/span&gt; table1 &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;47342&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzluser11 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;37&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;192683&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;37&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;192699&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; WALWrite &lt;span style="color:#f92672"&gt;|&lt;/span&gt; IO &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;insert&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;into&lt;/span&gt; table1 &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;75399&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzluser11 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;45&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;743023&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;45&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;743024&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; WALWrite &lt;span style="color:#f92672"&gt;|&lt;/span&gt; IO &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;update&lt;/span&gt; table1 &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;221993&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzluser11 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;46&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;184532&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;46&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;184541&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; WALWrite &lt;span style="color:#f92672"&gt;|&lt;/span&gt; IO &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;insert&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;into&lt;/span&gt; table1 &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;然而检查当时IO性能，写入15M/s并不高，与其他时间段相比甚至比较低，w_await同样很低&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Device: rrqm&lt;span style="color:#f92672"&gt;/&lt;/span&gt;s wrqm&lt;span style="color:#f92672"&gt;/&lt;/span&gt;s r&lt;span style="color:#f92672"&gt;/&lt;/span&gt;s w&lt;span style="color:#f92672"&gt;/&lt;/span&gt;s rkB&lt;span style="color:#f92672"&gt;/&lt;/span&gt;s wkB&lt;span style="color:#f92672"&gt;/&lt;/span&gt;s avgrq&lt;span style="color:#f92672"&gt;-&lt;/span&gt;sz avgqu&lt;span style="color:#f92672"&gt;-&lt;/span&gt;sz await r_await w_await svctm &lt;span style="color:#f92672"&gt;%&lt;/span&gt;util
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dm&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;322&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0.00&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0.00&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;187.00&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1515.00&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3572.00&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;15344.00&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;22.23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2.05&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1.20&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;9.39&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0.18&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0.15&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;25.70&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;没有强有力的证据显示是存储性能问题。&lt;/p&gt;
&lt;p&gt;目前来看应是瞬时并发insert value小事务，对flush wal时的锁争用。可以排除以下选项:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;并发小事务，不需要&lt;a href="https://www.postgresql.org/docs/16/wal-configuration.html" target="_blank" rel="noreferrer"&gt;调整wal buffer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;wal日志量不大，不需要开启&lt;a href="https://dba.stackexchange.com/questions/338319/postgres-walwrite-waits-whats-the-bottleneck" target="_blank" rel="noreferrer"&gt;日志压缩&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;FPI不多，不需要调整checkpoint&lt;/li&gt;
&lt;li&gt;IO压力不大，不需要&lt;a href="https://docs.dbmarlin.com/docs/kb/wait-events/postgresql/walwritelock/" target="_blank" rel="noreferrer"&gt;提升IO性能&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;至少可以有如下优化:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;开启数据库组提交（怕背锅可不调整，需要再测试）&lt;/li&gt;
&lt;li&gt;业务单个语句insert value语句合并提交，减少WALWriteLock锁争用&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title>案例-pg中的谓词越界和prepare statement问题</title><link>https://lastdba.com/2024/08/12/%E6%A1%88%E4%BE%8B-pg%E4%B8%AD%E7%9A%84%E8%B0%93%E8%AF%8D%E8%B6%8A%E7%95%8C%E5%92%8Cprepare-statement%E9%97%AE%E9%A2%98/</link><pubDate>Mon, 12 Aug 2024 00:00:00 +0000</pubDate><guid>https://lastdba.com/2024/08/12/%E6%A1%88%E4%BE%8B-pg%E4%B8%AD%E7%9A%84%E8%B0%93%E8%AF%8D%E8%B6%8A%E7%95%8C%E5%92%8Cprepare-statement%E9%97%AE%E9%A2%98/</guid><description>&lt;h2 class="relative group"&gt;现象
 &lt;div id="现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;案例：执行计划发生变化，plan选择了错误的索引，sql由毫秒级变成秒级。后面收集统计信息后，业务sql还是慢，最后通过删除DAILY_DATE时间索引建立(DAILY_DATE,A_ID)组合索引才解决。
疑问：&lt;/p&gt;</description><content:encoded>
&lt;h2 class="relative group"&gt;现象
 &lt;div id="现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;案例：执行计划发生变化，plan选择了错误的索引，sql由毫秒级变成秒级。后面收集统计信息后，业务sql还是慢，最后通过删除DAILY_DATE时间索引建立(DAILY_DATE,A_ID)组合索引才解决。
疑问：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;优化器为什么选择DAILY_DATE索引，而不是选择率更好的A_ID索引？&lt;/li&gt;
&lt;li&gt;收集统计信息后为什么没有效果？&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 class="relative group"&gt;统计信息过旧
 &lt;div id="统计信息过旧" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%bb%9f%e8%ae%a1%e4%bf%a1%e6%81%af%e8%bf%87%e6%97%a7" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--简化后的sql
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; tablzl
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; A_ID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; IS_DELETE &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;N&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; DAILY_DATE &lt;span style="color:#f92672"&gt;=&lt;/span&gt; to_date(&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;yyyyMMdd&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;and&lt;/span&gt; PARTITION_KEY &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;and&lt;/span&gt; PARTITION_KEY &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;优化器选择DAILY_DATE索引而不是过滤性比较好的A_ID&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Append (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;44&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;83&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;204&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; tablzl_p202401_DAILY_DATE_idx &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; tablzl_p202401 tablzl_1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;44&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;47&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;203&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (DAILY_DATE &lt;span style="color:#f92672"&gt;=&lt;/span&gt; to_date(&lt;span style="color:#e6db74"&gt;&amp;#39;20240223&amp;#39;&lt;/span&gt;::text, &lt;span style="color:#e6db74"&gt;&amp;#39;yyyyMMdd&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((partition_key &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;202401&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (partition_key &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;202402&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((A_ID)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;ID1234567890987654321&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((is_delete)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;N&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; tablzl_p202402_DAILY_DATE_idx &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; tablzl_p202402 tablzl_2 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;44&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;35&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;204&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (DAILY_DATE &lt;span style="color:#f92672"&gt;=&lt;/span&gt; to_date(&lt;span style="color:#e6db74"&gt;&amp;#39;20240223&amp;#39;&lt;/span&gt;::text, &lt;span style="color:#e6db74"&gt;&amp;#39;yyyyMMdd&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((partition_key &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;202401&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (partition_key &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;202402&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((A_ID)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;ID1234567890987654321&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((is_delete)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;N&amp;#39;&lt;/span&gt;::text))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;对于p202401分区，走DAILY_DATE还是A_ID索引，差别不大，因为1月分区没有2月23日的数据&lt;/li&gt;
&lt;li&gt;对于p202402分区，走DAILY_DATE还是A_ID索引，差别很大。走DAILY_DATE索引，它的预估cost=3.35，rows=1，实际上有上百万的数据，跑了2秒&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;p202402的统计信息中有MCV：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_stats &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; tablename&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;tablzl_p202402&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;and&lt;/span&gt; attname&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;DAILY_DATE&amp;#39;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;gx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;most_common_vals &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;{&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;19&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;17&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;07&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;06&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;03&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;31&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;13&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;most_common_freqs &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;{&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0481&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;047766667&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0466&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0449&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0441&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;043833334&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;043733332&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;043466665&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;043133333&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;043066666&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;042366665&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;041866668&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;041366667&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;041366667&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;039766666&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0394&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;039333332&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;..
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;038766667&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;03863333&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0381&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;038066667&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;037966665&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;037566666&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;036733333&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;计算MCV的总频率sum(most_common_freqs)&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0481&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;047766667&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0466&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0449&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0441&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;043833334&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;043733332&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;043466665&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;043133333&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;043066666&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;042366665&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;041866668&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;041366667&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;041366667&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;039766666&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0394&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;039333332&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;038766667&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;03863333&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0381&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;038066667&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;037966665&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;037566666&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;036733333&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;?&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;column&lt;/span&gt;&lt;span style="color:#f92672"&gt;?&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;999999990&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;刚好是1，代表1-22日就是这个分区的所有数据（预估），23日的数据应该是0条，所以planner在预估23日的数据时rows=1，所以选择了DAILY_DATE索引。实际上23日的数据有百万条。
本质上这是一个统计信息过久造成的问题。为什么前22天没有问题而且23日没有触发自动收集呢？&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; relname,reloptions &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_class &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; relname&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;tablzl&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; relname &lt;span style="color:#f92672"&gt;|&lt;/span&gt; reloptions 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;----------------------------+------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tablzl &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;show&lt;/span&gt; autovacuum_analyze_scale_factor;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; autovacuum_analyze_scale_factor 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;---------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;触发阈值默认是0.1，数据变化达到1/10的时候才会触发自动analyze。这是一个月分区，数据是每天插入和更新的，月初时1天写入200w数据，因为数据存量少，会触发多次analyze（threshold默认50可以忽略不记），而在月末时，比如23日，1天写入200w数据，不会触发analyze，因为只写了1/23。这个场景中插入后还会更新，插入200w更新200w，所以23日的数据变化是1/11左右，刚好不会触发analyze，&lt;strong&gt;这也能解释前20天运行稳定&lt;/strong&gt;。
另外，因为数据量的变化阈值是一个比例，每天的数据量的变化只要是比较均匀的，都会有这个月末统计信息不准的问题！&lt;/p&gt;

&lt;h2 class="relative group"&gt;执行计划缓存
 &lt;div id="执行计划缓存" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%89%a7%e8%a1%8c%e8%ae%a1%e5%88%92%e7%bc%93%e5%ad%98" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;因为是统计信息过旧问题，手动收集统计信息理应解决这个问题，实际上收集了以后业务sql还是慢。
analyze了以后，手动explain analyze 执行计划却是正确的。
说明analyze应该是有用的，但是没有影响到业务会话。由于sql执行用的是长会话，怀疑jdbc中使用prepare statement缓存执行计划（&lt;a href="https://jenkov.com/tutorials/jdbc/preparedstatement.html#:~:text=JDBC%20PreparedStatement%201%20Creating%20a%20PreparedStatement%20Before%20you,Reusing%20a%20PreparedStatement%20...%205%20PreparedStatement%20Performance%20" target="_blank" rel="noreferrer"&gt;jdbc prepare statement&lt;/a&gt;）。
而prepare statement在pg13（rasesql 1.3）中，收集统计信息不会失效，只能通过重连会话的方式重写解析。
prepare statement会生产一个通用执行计划（generic plan），由于统计信息不准确，通用执行计划跟传参执行计划一样，可以选择错误的索引&lt;/p&gt;

&lt;h2 class="relative group"&gt;prepare statement的特性
 &lt;div id="prepare-statement的特性" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#prepare-statement%e7%9a%84%e7%89%b9%e6%80%a7" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;psql支持prepare statement，由&lt;code&gt;plan_cache_mode&lt;/code&gt;参数控制&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;auto&lt;/code&gt;：默认，五次机制处理&lt;/li&gt;
&lt;li&gt;&lt;code&gt;force_custom_plan&lt;/code&gt;：永远进行硬解析，生成custom plan&lt;/li&gt;
&lt;li&gt;&lt;code&gt;force_generic_plan&lt;/code&gt;：永远使用generic plan，绑定变量&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;使用语法：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;PREPARE&lt;/span&gt; plan1(text,integer) &lt;span style="color:#66d9ef"&gt;AS&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; tlzl1 &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;and&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;month&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;EXECUTE&lt;/span&gt; plan1(&lt;span style="color:#e6db74"&gt;&amp;#39;256ac66bb53d31bc6124294238d6410c&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;11&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;deallocate&lt;/span&gt; plan1&lt;span style="color:#f92672"&gt;|&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;all&lt;/span&gt;; &lt;span style="color:#75715e"&gt;--使prepare失效，断开会话也可以&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;视图：（基本没用，因为是本地的，生产可看不到东西）&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_prepared_statements;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 class="relative group"&gt;generic plan是怎么生成的
 &lt;div id="generic-plan是怎么生成的" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#generic-plan%e6%98%af%e6%80%8e%e4%b9%88%e7%94%9f%e6%88%90%e7%9a%84" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;正常来说prepare语句跑5次是可以生成generic plan的。网上很多演示，这里就不演示正常情况了，以下是我测试出的“神奇”现象&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--准备数据
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; tlzl1(id varchar(&lt;span style="color:#ae81ff"&gt;50&lt;/span&gt;),&lt;span style="color:#66d9ef"&gt;month&lt;/span&gt; int);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;INSERT&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;INTO&lt;/span&gt; tlzl1 &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; md5(&lt;span style="color:#66d9ef"&gt;g&lt;/span&gt;::text),&lt;span style="color:#66d9ef"&gt;EXTRACT&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;month&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;g&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; generate_series(&lt;span style="color:#e6db74"&gt;&amp;#39;2023-01-01&amp;#39;&lt;/span&gt;::date, &lt;span style="color:#e6db74"&gt;&amp;#39;2023-11-30&amp;#39;&lt;/span&gt;::date, &lt;span style="color:#e6db74"&gt;&amp;#39;1 minute&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;g&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; idx_id &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; tlzl1(id);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; idx_month &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; tlzl1(&lt;span style="color:#66d9ef"&gt;month&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt; tlzl;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--执行prepare语句
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;PREPARE&lt;/span&gt; plan1(text,integer) &lt;span style="color:#66d9ef"&gt;AS&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; tlzl1 &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;and&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;month&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;EXECUTE&lt;/span&gt; plan1(&lt;span style="color:#e6db74"&gt;&amp;#39;256ac66bb53d31bc6124294238d6410c&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;11&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;EXECUTE&lt;/span&gt; plan1(&lt;span style="color:#e6db74"&gt;&amp;#39;256ac66bb53d31bc6124294238d6410c&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;11&amp;#39;&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;注意这里只插入11月前的数据，12月是没有数据的。此时查12月数据可以走到month索引&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;EXECUTE&lt;/span&gt; plan1(&lt;span style="color:#e6db74"&gt;&amp;#39;256ac66bb53d31bc6124294238d6410c&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;12&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;------------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_month &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; tlzl1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;94&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;37&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;035&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;036&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (&lt;span style="color:#66d9ef"&gt;month&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((id)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;256ac66bb53d31bc6124294238d6410c&amp;#39;&lt;/span&gt;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;170&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Execution Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;058&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;551&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;EXECUTE&lt;/span&gt; plan1(&lt;span style="color:#e6db74"&gt;&amp;#39;256ac66bb53d31bc6124294238d6410c&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;12&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;------------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_month &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; tlzl1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;94&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;37&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;021&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;021&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (&lt;span style="color:#66d9ef"&gt;month&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((id)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;256ac66bb53d31bc6124294238d6410c&amp;#39;&lt;/span&gt;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;168&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Execution Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;046&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;488&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;EXECUTE&lt;/span&gt; plan1(&lt;span style="color:#e6db74"&gt;&amp;#39;256ac66bb53d31bc6124294238d6410c&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;12&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;------------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_month &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; tlzl1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;94&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;37&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;017&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;018&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (&lt;span style="color:#66d9ef"&gt;month&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((id)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;256ac66bb53d31bc6124294238d6410c&amp;#39;&lt;/span&gt;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;157&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Execution Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;040&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;419&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;EXECUTE&lt;/span&gt; plan1(&lt;span style="color:#e6db74"&gt;&amp;#39;256ac66bb53d31bc6124294238d6410c&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;12&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;------------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_month &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; tlzl1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;94&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;37&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;019&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;020&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (&lt;span style="color:#66d9ef"&gt;month&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((id)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;256ac66bb53d31bc6124294238d6410c&amp;#39;&lt;/span&gt;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;160&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Execution Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;044&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;479&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;EXECUTE&lt;/span&gt; plan1(&lt;span style="color:#e6db74"&gt;&amp;#39;256ac66bb53d31bc6124294238d6410c&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;12&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;------------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_month &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; tlzl1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;94&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;37&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;018&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;018&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (&lt;span style="color:#66d9ef"&gt;month&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((id)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;256ac66bb53d31bc6124294238d6410c&amp;#39;&lt;/span&gt;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;155&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Execution Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;041&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;426&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--第六次
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;EXECUTE&lt;/span&gt; plan1(&lt;span style="color:#e6db74"&gt;&amp;#39;256ac66bb53d31bc6124294238d6410c&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;12&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;---------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_id &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; tlzl1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;44&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;37&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;044&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;045&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((id)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (&lt;span style="color:#66d9ef"&gt;month&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Rows&lt;/span&gt; Removed &lt;span style="color:#66d9ef"&gt;by&lt;/span&gt; Filter: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;023&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Execution Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;079&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;第六次绑定了generic plan，但是并不是前五次的plan，走的是id索引。如果id的重复度再高点的话，也可以测出来绑不上generic plan的场景（未展示）。
这里就要看下源码了
&lt;code&gt;choose_custom_plan&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;choose_custom_plan&lt;/span&gt;(CachedPlanSource &lt;span style="color:#f92672"&gt;*&lt;/span&gt;plansource, ParamListInfo boundParams)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/* Generate custom plans until we have done at least 5 (arbitrary) */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (plansource&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;num_custom_plans &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	avg_custom_cost &lt;span style="color:#f92672"&gt;=&lt;/span&gt; plansource&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;total_custom_cost &lt;span style="color:#f92672"&gt;/&lt;/span&gt; plansource&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;num_custom_plans;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * Prefer generic plan if it&amp;#39;s less expensive than the average custom
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * plan. (Because we include a charge for cost of planning in the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * custom-plan costs, this means the generic plan only has to be less
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * expensive than the execution cost plus replan cost of the custom
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * plans.)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * Note that if generic_cost is -1 (indicating we&amp;#39;ve not yet determined
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * the generic plan cost), we&amp;#39;ll always prefer generic at this point.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (plansource&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;generic_cost &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; avg_custom_cost)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; false;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}		
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;只要generic plan的cost 小于 前5次的custom_cost平均值，那么就使用generic plan。
虽然5次机制众所周知，但是需要注意generic plan是怎么生成的。第5次时还没有generic plan（刚开始的时候），generic_cost=-1，会直接返回&lt;code&gt;GetCachedPlan&lt;/code&gt;中的&lt;code&gt;!customplan&lt;/code&gt;逻辑&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CachedPlan &lt;span style="color:#f92672"&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;GetCachedPlan&lt;/span&gt;(CachedPlanSource &lt;span style="color:#f92672"&gt;*&lt;/span&gt;plansource, ParamListInfo boundParams,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			 &lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt; useResOwner, QueryEnvironment &lt;span style="color:#f92672"&gt;*&lt;/span&gt;queryEnv)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	customplan &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;choose_custom_plan&lt;/span&gt;(plansource, boundParams);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;customplan)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;CheckCachedPlan&lt;/span&gt;(plansource))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/* We want a generic plan, and we already have a valid one */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			plan &lt;span style="color:#f92672"&gt;=&lt;/span&gt; plansource&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;gplan;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;Assert&lt;/span&gt;(plan&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;magic &lt;span style="color:#f92672"&gt;==&lt;/span&gt; CACHEDPLAN_MAGIC);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/* Build a new generic plan */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			plan &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;BuildCachedPlan&lt;/span&gt;(plansource, qlist, NULL, queryEnv);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/* Just make real sure plansource-&amp;gt;gplan is clear */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;ReleaseGenericPlan&lt;/span&gt;(plansource);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/* Link the new generic plan into the plansource */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			plansource&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;gplan &lt;span style="color:#f92672"&gt;=&lt;/span&gt; plan;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			plan&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;refcount&lt;span style="color:#f92672"&gt;++&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/* Immediately reparent into appropriate context */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (plansource&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;is_saved)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#75715e"&gt;/* saved plans all live under CacheMemoryContext */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;MemoryContextSetParent&lt;/span&gt;(plan&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;context, CacheMemoryContext);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				plan&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;is_saved &lt;span style="color:#f92672"&gt;=&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#75715e"&gt;/* otherwise, it should be a sibling of the plansource */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#a6e22e"&gt;MemoryContextSetParent&lt;/span&gt;(plan&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;context,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;									 &lt;span style="color:#a6e22e"&gt;MemoryContextGetParent&lt;/span&gt;(plansource&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;context));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/* Update generic_cost whenever we make a new generic plan */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			plansource&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;generic_cost &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;cached_plan_cost&lt;/span&gt;(plan, false);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * If, based on the now-known value of generic_cost, we&amp;#39;d not have
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * chosen to use a generic plan, then forget it and make a custom
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * plan. This is a bit of a wart but is necessary to avoid a
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * glitch in behavior when the custom plans are consistently big
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * winners; at some point we&amp;#39;ll experiment with a generic plan and
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * find it&amp;#39;s a loser, but we don&amp;#39;t want to actually execute that
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * plan.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			customplan &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;choose_custom_plan&lt;/span&gt;(plansource, boundParams);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * If we choose to plan again, we need to re-copy the query_list,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * since the planner probably scribbled on it. We can force
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 * BuildCachedPlan to do that by passing NIL.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;			 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			qlist &lt;span style="color:#f92672"&gt;=&lt;/span&gt; NIL;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; plan;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}	
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;!customplan&lt;/code&gt;逻辑中，如果有generic plan直接使用，没有的话通过&lt;code&gt;BuildCachedPlan&lt;/code&gt;生成一个plan，&lt;code&gt;BuildCachedPlan&lt;/code&gt;就是生成plan的主体逻辑，通过query tree生成plan tree。
没有参数怎么办？注释已经说明，没有参数就传NULL进去，到生成plan的逻辑&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;To build a generic, parameter&lt;span style="color:#f92672"&gt;-&lt;/span&gt;value&lt;span style="color:#f92672"&gt;-&lt;/span&gt;independent plan, pass NULL &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; boundParams. To build a custom plan, pass the actual parameter values via
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; boundParams&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;传NULL优化器更prefer什么执行计划？这部分代码逻辑有些复杂。从优化器的角度考虑，可能是有多个plan可以选择的，但总得选一个作为generic plan
而选出来那个generic plan，才可以对比前5次的plan cost。
为什么用更低cost的执行计划反复执行，没有生成想要的generic plan？
&lt;strong&gt;generic plan长什么样跟前五次的执行计划没有关系，前五次只是决定了是否绑定这个generic plan&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;从优化器设计的角度来考虑，generic plan是为了减少解析时间提高sql执行效率，适合多而小的查询。问题在于generic plan本身很粗糙，postgres引进五次机制就是为了来减少generic plan本身是稀烂的可能性。
即使有五次机制，还是导致绑定的烂generic plan的原因：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;generic plan也是plan，本身就可能烂&lt;/li&gt;
&lt;li&gt;统计信息不准确，generic plan的cost预估很低&lt;/li&gt;
&lt;li&gt;前五次的传参选择率低（或其他影响）导致custom plan cost高&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;prepare statement的失效
 &lt;div id="prepare-statement的失效" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#prepare-statement%e7%9a%84%e5%a4%b1%e6%95%88" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;除了DDL、deallocate、断开会话，收集统计信息也会让prepared statement，不过这是pg14的特性。
pg13:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;PostgreSQL will force re-analysis and re-planning of the statement before using it whenever database objects used in the statement have undergone definitional (DDL) changes since the previous use of the prepared statement&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;pg14:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;PostgreSQL will force re-analysis and re-planning of the statement before using it whenever database objects used in the statement have undergone definitional (DDL) changes or their planner statistics have been updated since the previous use of the prepared statement&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;pg13 收集统计信息不会让prepare statement失效的测试：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;EXECUTE&lt;/span&gt; plan1(&lt;span style="color:#e6db74"&gt;&amp;#39;256ac66bb53d31bc6124294238d6410c&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;11&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;---------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_id &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; tlzl1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;44&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;37&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;033&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;033&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((id)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (&lt;span style="color:#66d9ef"&gt;month&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Rows&lt;/span&gt; Removed &lt;span style="color:#66d9ef"&gt;by&lt;/span&gt; Filter: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;098&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Execution Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;050&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_prepared_statements;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;statement&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; prepare_time &lt;span style="color:#f92672"&gt;|&lt;/span&gt; parameter_types &lt;span style="color:#f92672"&gt;|&lt;/span&gt; from_sql 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-------+-----------------------------------------------+-------------------------------+-----------------+----------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; plan1 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PREPARE&lt;/span&gt; plan1(text,integer) &lt;span style="color:#66d9ef"&gt;AS&lt;/span&gt; &lt;span style="color:#f92672"&gt;+|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;59&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;966733&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;{&lt;/span&gt;text,integer&lt;span style="color:#960050;background-color:#1e0010"&gt;}&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; tlzl1 &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;and&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;month&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;row&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt; tlzl1;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;ANALYZE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_prepared_statements;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;statement&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; prepare_time &lt;span style="color:#f92672"&gt;|&lt;/span&gt; parameter_types &lt;span style="color:#f92672"&gt;|&lt;/span&gt; from_sql 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-------+-----------------------------------------------+-------------------------------+-----------------+----------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; plan1 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PREPARE&lt;/span&gt; plan1(text,integer) &lt;span style="color:#66d9ef"&gt;AS&lt;/span&gt; &lt;span style="color:#f92672"&gt;+|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;59&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;966733&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;{&lt;/span&gt;text,integer&lt;span style="color:#960050;background-color:#1e0010"&gt;}&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; tlzl1 &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;and&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;month&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;row&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;EXECUTE&lt;/span&gt; plan1(&lt;span style="color:#e6db74"&gt;&amp;#39;256ac66bb53d31bc6124294238d6410c&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;11&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;---------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_id &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; tlzl1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;44&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;37&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;051&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;052&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((id)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (&lt;span style="color:#66d9ef"&gt;month&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Rows&lt;/span&gt; Removed &lt;span style="color:#66d9ef"&gt;by&lt;/span&gt; Filter: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;022&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Execution Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;098&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 class="relative group"&gt;jdbc的prepare statement
 &lt;div id="jdbc的prepare-statement" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#jdbc%e7%9a%84prepare-statement" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;prepare statement不是PG的独有功能，一些数据库也有相关的预解析特性，比如oracle也可以实现类似的功能。
&lt;a href="https://jenkov.com/tutorials/jdbc/preparedstatement.html#:~:text=JDBC%20PreparedStatement%201%20Creating%20a%20PreparedStatement%20Before%20you,Reusing%20a%20PreparedStatement%20...%205%20PreparedStatement%20Performance%20" target="_blank" rel="noreferrer"&gt;jdbc&lt;/a&gt;自身也可以调用数据库的预解析接口，直接显示使用 prepare statement。
jdbc参考配置：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;String &lt;span style="color:#66d9ef"&gt;sql&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;select * from people where id=?&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PreparedStatement preparedStatement &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;connection&lt;/span&gt;.prepareStatement(&lt;span style="color:#66d9ef"&gt;sql&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 class="relative group"&gt;建议
 &lt;div id="建议" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%bb%ba%e8%ae%ae" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;调小表级的&lt;code&gt;autovacuum_analyze_scale_factor=0.02&lt;/code&gt;（why 0.02？0.02&amp;lt;1/31)。因为是边写边查，手动收集不太好定时间，调小&lt;code&gt;autovacuum_analyze_scale_factor&lt;/code&gt;只能减缓这个问题。&lt;/li&gt;
&lt;li&gt;考虑去掉jdbc中的prepare设置，或者设置&lt;code&gt;force_custom_plan&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;调整sql逻辑&lt;/li&gt;
&lt;li&gt;调整索引。4.1删除不必要的时间索引；4.2将越界后走的索引重建为包含id字段的组合索引（一个不错的建议）。&lt;/li&gt;
&lt;li&gt;应急流程：统计信息收集后业务未恢复的情况，确认手动explain执行计划改变的情况下，可以考虑杀会话(13以前)。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;最后，谓词越界问题基本上在所有数据库中都有，特别是在时间字段上。现有手段其实没有一个比较简单又能完美解决的办法，oracle的SPM好感度又+1&amp;hellip;&lt;/p&gt;</content:encoded></item><item><title>案例：逻辑复制把checkpoint、walsender、backup全部卡死</title><link>https://lastdba.com/2024/08/12/%E6%A1%88%E4%BE%8B%E9%80%BB%E8%BE%91%E5%A4%8D%E5%88%B6%E6%8A%8Acheckpointwalsenderbackup%E5%85%A8%E9%83%A8%E5%8D%A1%E6%AD%BB/</link><pubDate>Mon, 12 Aug 2024 00:00:00 +0000</pubDate><guid>https://lastdba.com/2024/08/12/%E6%A1%88%E4%BE%8B%E9%80%BB%E8%BE%91%E5%A4%8D%E5%88%B6%E6%8A%8Acheckpointwalsenderbackup%E5%85%A8%E9%83%A8%E5%8D%A1%E6%AD%BB/</guid><description>&lt;h2 class="relative group"&gt;问题现象
 &lt;div id="问题现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;备份进程命令pg_start_backup()被checkpoint进程阻塞，checkpoint被逻辑复制walsender进程阻塞。业务虽然还在继续运行，但是备份、checkpoint、逻辑复制全部hang死。&lt;/p&gt;</description><content:encoded>
&lt;h2 class="relative group"&gt;问题现象
 &lt;div id="问题现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;备份进程命令pg_start_backup()被checkpoint进程阻塞，checkpoint被逻辑复制walsender进程阻塞。业务虽然还在继续运行，但是备份、checkpoint、逻辑复制全部hang死。&lt;/p&gt;
&lt;p&gt;pg_stat_activity 中有两个明显异常的等待事件：&lt;code&gt;replication_slot_io&lt;/code&gt; 。&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[postgres&lt;span style="color:#f92672"&gt;@&lt;/span&gt;hostlzl:&lt;span style="color:#ae81ff"&gt;6666&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;postgres][&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;50&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;28&lt;/span&gt;]&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_stat_activity &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; pid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;173038&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;gx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;[ RECORD &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; ]&lt;span style="color:#75715e"&gt;----+------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;datid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;17630&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;datname &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzldb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;173038&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;usesysid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;35157&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;usename &lt;span style="color:#f92672"&gt;|&lt;/span&gt; repuser
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;application_name &lt;span style="color:#f92672"&gt;|&lt;/span&gt; PostgreSQL JDBC Driver
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;client_addr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;88&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;75&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;58&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;client_hostname &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;client_port &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;37623&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;backend_start &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;40&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;07&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;75022&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xact_start &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;query_start &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;state_change &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;40&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;07&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;764475&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;wait_event_type &lt;span style="color:#f92672"&gt;|&lt;/span&gt; LWLock
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;wait_event &lt;span style="color:#f92672"&gt;|&lt;/span&gt; replication_slot_io
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;backend_xid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;backend_xmin &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;query &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;backend_type &lt;span style="color:#f92672"&gt;|&lt;/span&gt; walsender
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Time: &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;658&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[postgres&lt;span style="color:#f92672"&gt;@&lt;/span&gt;hostlzl:&lt;span style="color:#ae81ff"&gt;6666&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;postgres][&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;50&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;34&lt;/span&gt;]&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_stat_activity &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; pid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;12729&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;gx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;[ RECORD &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; ]&lt;span style="color:#75715e"&gt;----+------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;datid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;datname &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;12729&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;usesysid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;usename &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;application_name &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;client_addr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;client_hostname &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;client_port &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;backend_start &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;03&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;343116&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xact_start &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;query_start &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;state_change &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;wait_event_type &lt;span style="color:#f92672"&gt;|&lt;/span&gt; LWLock
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;wait_event &lt;span style="color:#f92672"&gt;|&lt;/span&gt; replication_slot_io
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;backend_xid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;backend_xmin &lt;span style="color:#f92672"&gt;|&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;query &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;backend_type &lt;span style="color:#f92672"&gt;|&lt;/span&gt; checkpointer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;一个是walsender进程，一个是checkpointer进程。都是4月2日启动的进程，直接查看4月2日walsender 173038的日志：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--repuser log
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-04-02 11:40:07.750 CST,,,173038,&lt;span style="color:#e6db74"&gt;&amp;#34;30.88.75.58:37623&amp;#34;&lt;/span&gt;,660b7e17.2a3ee,1,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,2024-04-02 11:40:07 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;connection received: host=30.88.75.58 port=37623&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-04-02 11:40:07.756 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;repuser&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,173038,&lt;span style="color:#e6db74"&gt;&amp;#34;30.88.75.58:37623&amp;#34;&lt;/span&gt;,660b7e17.2a3ee,2,&lt;span style="color:#e6db74"&gt;&amp;#34;authentication&amp;#34;&lt;/span&gt;,2024-04-02 11:40:07 CST,32/30,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;replication connection authorized: user=repuser&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-04-02 11:40:07.765 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;repuser&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,173038,&lt;span style="color:#e6db74"&gt;&amp;#34;30.88.75.58:37623&amp;#34;&lt;/span&gt;,660b7e17.2a3ee,3,&lt;span style="color:#e6db74"&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;,2024-04-02 11:40:07 CST,32/0,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;starting logical decoding for slot &amp;#34;&amp;#34;pg_lzldb_lzldb_ora_pgdb_pgdb&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;Streaming transactions committing after 4263/42E6EF88, reading WAL from 4263/41DAEBD0.&amp;#34;&lt;/span&gt;,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;PostgreSQL JDBC Driver&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-04-02 11:40:07.765 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;repuser&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,173038,&lt;span style="color:#e6db74"&gt;&amp;#34;30.88.75.58:37623&amp;#34;&lt;/span&gt;,660b7e17.2a3ee,4,&lt;span style="color:#e6db74"&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;,2024-04-02 11:40:07 CST,32/0,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;logical decoding found consistent point at 4263/41DAEBD0&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;There are no running transactions.&amp;#34;&lt;/span&gt;,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;PostgreSQL JDBC Driver&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;173038这个walsender进程只能看到start启动链路信息，后面这个walsender再也没有输出过日志，很有可能从那个时候起开始hang了。
不过再往前翻一点，还可以看到相同复制链路的walsender信息（walsender进程号不同，slot name相同）：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--84918 之前的启动日志
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-04-02 11:30:07.498 CST,,,84918,&lt;span style="color:#e6db74"&gt;&amp;#34;30.88.75.58:54898&amp;#34;&lt;/span&gt;,660b7bbf.14bb6,1,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,2024-04-02 11:30:07 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;connection received: host=30.88.75.58 port=54898&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-04-02 11:30:07.504 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;repuser&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,84918,&lt;span style="color:#e6db74"&gt;&amp;#34;30.88.75.58:54898&amp;#34;&lt;/span&gt;,660b7bbf.14bb6,2,&lt;span style="color:#e6db74"&gt;&amp;#34;authentication&amp;#34;&lt;/span&gt;,2024-04-02 11:30:07 CST,30/3,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;replication connection authorized: user=repuser&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-04-02 11:30:07.514 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;repuser&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,84918,&lt;span style="color:#e6db74"&gt;&amp;#34;30.88.75.58:54898&amp;#34;&lt;/span&gt;,660b7bbf.14bb6,3,&lt;span style="color:#e6db74"&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;,2024-04-02 11:30:07 CST,30/0,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;starting logical decoding for slot &amp;#34;&amp;#34;pg_lzldb_lzldb_ora_pgdb_pgdb&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;Streaming transactions committing after 4263/41DADE38, reading WAL from 4263/358F1340.&amp;#34;&lt;/span&gt;,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;PostgreSQL JDBC Driver&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-04-02 11:30:07.516 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;repuser&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,84918,&lt;span style="color:#e6db74"&gt;&amp;#34;30.88.75.58:54898&amp;#34;&lt;/span&gt;,660b7bbf.14bb6,4,&lt;span style="color:#e6db74"&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;,2024-04-02 11:30:07 CST,30/0,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;logical decoding found consistent point at 4263/358F1340&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;There are no running transactions.&amp;#34;&lt;/span&gt;,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;PostgreSQL JDBC Driver&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-04-02 11:36:07.061 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;repuser&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,86630,&lt;span style="color:#e6db74"&gt;&amp;#34;30.88.75.58:45227&amp;#34;&lt;/span&gt;,660b7bca.15266,5,&lt;span style="color:#e6db74"&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;,2024-04-02 11:30:18 CST,30/0,0,ERROR,XX000,&lt;span style="color:#e6db74"&gt;&amp;#34;could not write to file &amp;#34;&amp;#34;pg_replslot/pg_lzldb_lzldb_ora_pgdb_pgdb/state.tmp&amp;#34;&amp;#34;: Cannot allocate memory&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;PostgreSQL JDBC Driver&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-04-02 11:36:40.151 CST,&lt;span style="color:#e6db74"&gt;&amp;#34;repuser&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,86630,&lt;span style="color:#e6db74"&gt;&amp;#34;30.88.75.58:45227&amp;#34;&lt;/span&gt;,660b7bca.15266,6,&lt;span style="color:#e6db74"&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;,2024-04-02 11:30:18 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;disconnection: session time: 0:06:21.760 user=repuser database=lzldb host=30.88.75.58 port=45227&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;PostgreSQL JDBC Driver&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这个复制槽在11:30:07也启动过一次，并且过了6分钟后，因为内存打满导致写入&lt;code&gt;state.tmp&lt;/code&gt;失败。
同样的，上面查出来的checkpoint进程12729，也报了相同的state.tmp文件错误&lt;code&gt;pg_replslot/pg_lzldb_lzldb_ora_pgdb_pgdb/state.tmp&amp;quot;&amp;quot;: File exists&amp;quot;&lt;/code&gt;，该报错在复制槽报错后的半分钟出现：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--checkpoint log
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-04-02 11:36:39.925 CST,,,12729,,660b7a17.31b9,4,,2024-04-02 11:23:03 CST,,0,LOG,58P02,&lt;span style="color:#e6db74"&gt;&amp;#34;could not create file &amp;#34;&amp;#34;pg_replslot/pg_lzldb_lzldb_ora_pgdb_pgdb/state.tmp&amp;#34;&amp;#34;: File exists&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-04-02 11:36:40.151 CST,,,12729,,660b7a17.31b9,5,,2024-04-02 11:23:03 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;checkpoint complete: wrote 334 buffers (0.0%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.108 s, sync=0.082 s, total=217.083 s; sync files=139, longest=0.004 s, average=0.000 s; distance=2295 kB, estimate=2295 kB&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-04-02 11:48:03.414 CST,,,12729,,660b7a17.31b9,6,,2024-04-02 11:23:03 CST,,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;checkpoint starting: time&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;checkpoint此后再也没有出现过日志输出，看起来跟walsender一样，hang住了。&lt;/p&gt;
&lt;p&gt;通过搜索&lt;code&gt;pg_replslot/pg_lzldb_lzldb_ora_pgdb_pgdb/state.tmp&amp;quot;&amp;quot;: File exists&amp;quot;&lt;/code&gt;可以快速又简单的找到社区邮件：&lt;a href="https://www.postgresql.org/message-id/14b3454f-2d68-c637-68e4-2b42ff976168%40postgrespro.ru" target="_blank" rel="noreferrer"&gt;https://www.postgresql.org/message-id/14b3454f-2d68-c637-68e4-2b42ff976168%40postgrespro.ru&lt;/a&gt;
它真正的修复版本是&lt;a href="https://www.postgresql.org/docs/release/12.3/" target="_blank" rel="noreferrer"&gt;PG12.3&lt;/a&gt;：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Ensure that a replication slot&amp;rsquo;s io_in_progress_lock is released in failure code paths (Pavan Deolasee)
This could result in a walsender later becoming stuck waiting for the lock.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 class="relative group"&gt;深入分析
 &lt;div id="深入分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%b7%b1%e5%85%a5%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;虽然找到了bug，但其实很多问题没有搞清楚：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;walsender和checkpoints为什么hang住了？&lt;/li&gt;
&lt;li&gt;walsender和checkpoints是谁阻塞了谁？&lt;/li&gt;
&lt;li&gt;怎么触发的？&lt;/li&gt;
&lt;li&gt;有什么解决方案？&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;源码分析
 &lt;div id="源码分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%ba%90%e7%a0%81%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;当前版本为11.5。&lt;/p&gt;
&lt;p&gt;walsender和checkpointer两个进程的的pstack：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;postgres@hostlzl:lzldb:6666: /pg/pg6666/data/pg_log&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ pstack &lt;span style="color:#ae81ff"&gt;173038&lt;/span&gt; &lt;span style="color:#75715e"&gt;##walsender&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#0 0x00002b9eec171a0b in do_futex_wait.constprop.1 () from /lib64/libpthread.so.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#1 0x00002b9eec171a9f in __new_sem_wait_slow.constprop.0 () from /lib64/libpthread.so.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#2 0x00002b9eec171b3b in sem_wait@@GLIBC_2.2.5 () from /lib64/libpthread.so.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#3 0x00000000006b2512 in PGSemaphoreLock (sema=0x2b9ef5fdb0b8) at pg_sema.c:316&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#4 0x000000000071e94c in LWLockAcquire (lock=lock@entry=0x2babd8cee5b8, mode=mode@entry=LW_EXCLUSIVE) at lwlock.c:1243&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#5 0x00000000006ef7cb in SaveSlotToPath (slot=0x2babd8cee500, dir=dir@entry=0x7ffcaffd79f0 &amp;#34;pg_replslot/pg_lzldb_lzldb_ora_pgdb_pgdb&amp;#34;, elevel=elevel@entry=20) at slot.c:1249&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#6 0x00000000006f0515 in ReplicationSlotSave () at slot.c:653&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#7 0x00000000006d75d8 in LogicalConfirmReceivedLocation (lsn=&amp;lt;optimized out&amp;gt;) at logical.c:1049&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#8 0x00000000006d774d in LogicalIncreaseXminForSlot (current_lsn=current_lsn@entry=72994075200640, xmin=xmin@entry=1241611955) at logical.c:914&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#9 0x00000000006e0fb3 in SnapBuildProcessRunningXacts (builder=builder@entry=0x23146c0, lsn=72994075200640, running=running@entry=0x22e8978) at snapbuild.c:1146&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#10 0x00000000006d484c in DecodeStandbyOp (buf=0x7ffcaffd7eb0, buf=0x7ffcaffd7eb0, ctx=0x2209820) at decode.c:318&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#11 LogicalDecodingProcessRecord (ctx=0x2209820, record=&amp;lt;optimized out&amp;gt;) at decode.c:121&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#12 0x00000000006e50e0 in XLogSendLogical () at walsender.c:2799&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#13 0x00000000006e7122 in WalSndLoop (send_data=send_data@entry=0x6e5080 &amp;lt;XLogSendLogical&amp;gt;) at walsender.c:2162&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#14 0x00000000006e7d91 in StartLogicalReplication (cmd=0x22eedd8) at walsender.c:1109&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#15 exec_replication_command (cmd_string=cmd_string@entry=0x2210c48 &amp;#34;START_REPLICATION SLOT pg_lzldb_lzldb_ora_pgdb_pgdb LOGICAL 4263/42E6EF88 (\&amp;#34;add-tables\&amp;#34; &amp;#39;public.acr_finance_coa_partition_17_01,public.acr_finance_coa_partition_17_02,public.acr_finance_coa_part&amp;#34;...) at walsender.c:1541&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#16 0x000000000072c899 in PostgresMain (argc=&amp;lt;optimized out&amp;gt;, argv=argv@entry=0x2216f78, dbname=0x2216c98 &amp;#34;lzldb&amp;#34;, username=&amp;lt;optimized out&amp;gt;) at postgres.c:4178&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#17 0x000000000047e481 in BackendRun (port=0x220eda0) at postmaster.c:4358&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#18 BackendStartup (port=0x220eda0) at postmaster.c:4030&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#19 ServerLoop () at postmaster.c:1707&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#20 0x00000000006c4359 in PostmasterMain (argc=argc@entry=3, argv=argv@entry=0x21dbe90) at postmaster.c:1380&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#21 0x000000000047eefb in main (argc=3, argv=0x21dbe90) at main.c:228&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;postgres@hostlzl:lzldb:6666: /pg/pg6666/data/pg_wal&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ pstack &lt;span style="color:#ae81ff"&gt;12729&lt;/span&gt; &lt;span style="color:#75715e"&gt;##checkpointer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#0 0x00002b9eec171a0b in do_futex_wait.constprop.1 () from /lib64/libpthread.so.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#1 0x00002b9eec171a9f in __new_sem_wait_slow.constprop.0 () from /lib64/libpthread.so.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#2 0x00002b9eec171b3b in sem_wait@@GLIBC_2.2.5 () from /lib64/libpthread.so.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#3 0x00000000006b2512 in PGSemaphoreLock (sema=0x2b9ef5fdcd38) at pg_sema.c:316&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#4 0x000000000071e94c in LWLockAcquire (lock=lock@entry=0x2babd8cee5b8, mode=mode@entry=LW_EXCLUSIVE) at lwlock.c:1243&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#5 0x00000000006ef7cb in SaveSlotToPath (slot=slot@entry=0x2babd8cee500, dir=dir@entry=0x7ffcaffd6ee0 &amp;#34;pg_replslot/pg_lzldb_lzldb_ora_pgdb_pgdb&amp;#34;, elevel=elevel@entry=15) at slot.c:1249&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#6 0x00000000006f11a7 in CheckPointReplicationSlots () at slot.c:1100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#7 0x00000000004f674f in CheckPointGuts (checkPointRedo=72994093982360, flags=flags@entry=128) at xlog.c:9146&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#8 0x00000000004fcc77 in CreateCheckPoint (flags=flags@entry=128) at xlog.c:8937&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#9 0x00000000006b8312 in CheckpointerMain () at checkpointer.c:491&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#10 0x000000000050ba15 in AuxiliaryProcessMain (argc=argc@entry=2, argv=argv@entry=0x7ffcaffd7540) at bootstrap.c:451&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#11 0x00000000006c1cb9 in StartChildProcess (type=CheckpointerProcess) at postmaster.c:5337&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#12 0x00000000006c2f5a in reaper (postgres_signal_arg=&amp;lt;optimized out&amp;gt;) at postmaster.c:2867&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#13 &amp;lt;signal handler called&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#14 0x00002b9eed5ba783 in __select_nocancel () from /lib64/libc.so.6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#15 0x000000000047db38 in ServerLoop () at postmaster.c:1671&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#16 0x00000000006c4359 in PostmasterMain (argc=argc@entry=3, argv=argv@entry=0x21dbe90) at postmaster.c:1380&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#17 0x000000000047eefb in main (argc=3, argv=0x21dbe90) at main.c:228&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;最值得注意的是&lt;code&gt;LWLockAcquire&lt;/code&gt;这行的堆栈，walsender和checkpointer都有这样的进栈，并且他们俩都以排他模式申请了同一个LWLOCK地址：&lt;code&gt;lock=lock@entry=0x2babd8cee5b8, mode=mode@entry=LW_EXCLUSIVE&lt;/code&gt;，进入无限期的等待···
&lt;code&gt;LWLockAcquire&lt;/code&gt;的上一个堆栈函数便是&lt;code&gt;SaveSlotToPath&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;在&lt;code&gt;src/backend/replication/slot.c&lt;/code&gt;中找到关键问题函数源码&lt;code&gt;SaveSlotToPath&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//SaveSlotToPath用于存储slot的状态
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;SaveSlotToPath&lt;/span&gt;(ReplicationSlot &lt;span style="color:#f92672"&gt;*&lt;/span&gt;slot, &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;char&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;dir, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; elevel)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{	&lt;span style="color:#75715e"&gt;//11.5代码
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;char&lt;/span&gt;		tmppath[MAXPGPATH];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;char&lt;/span&gt;		path[MAXPGPATH];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;			fd;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	ReplicationSlotOnDisk cp;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt;		was_dirty;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/* and don&amp;#39;t do anything if there&amp;#39;s nothing to write */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;was_dirty)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;//函数开头获得LWLock，排他模式
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;LWLockAcquire&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;slot&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;io_in_progress_lock, LW_EXCLUSIVE);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;//注意fd的逻辑，报错与第二次walsender报错一致
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	fd &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;OpenTransientFile&lt;/span&gt;(tmppath, O_CREAT &lt;span style="color:#f92672"&gt;|&lt;/span&gt; O_EXCL &lt;span style="color:#f92672"&gt;|&lt;/span&gt; O_WRONLY &lt;span style="color:#f92672"&gt;|&lt;/span&gt; PG_BINARY);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (fd &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;ereport&lt;/span&gt;(elevel,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				(&lt;span style="color:#a6e22e"&gt;errcode_for_file_access&lt;/span&gt;(),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				 &lt;span style="color:#a6e22e"&gt;errmsg&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;could not create file &lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;%s&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;: %m&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						tmppath)));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;//写入fd文件的逻辑，报错与首次walsender报错一致
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; ((&lt;span style="color:#a6e22e"&gt;write&lt;/span&gt;(fd, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;cp, &lt;span style="color:#66d9ef"&gt;sizeof&lt;/span&gt;(cp))) &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;sizeof&lt;/span&gt;(cp))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;			save_errno &lt;span style="color:#f92672"&gt;=&lt;/span&gt; errno;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;pgstat_report_wait_end&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;CloseTransientFile&lt;/span&gt;(fd);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/* if write didn&amp;#39;t set errno, assume problem is no disk space */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		errno &lt;span style="color:#f92672"&gt;=&lt;/span&gt; save_errno &lt;span style="color:#f92672"&gt;?&lt;/span&gt; save_errno : ENOSPC;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;ereport&lt;/span&gt;(elevel,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				(&lt;span style="color:#a6e22e"&gt;errcode_for_file_access&lt;/span&gt;(),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				 &lt;span style="color:#a6e22e"&gt;errmsg&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;could not write to file &lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;%s&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;: %m&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						tmppath)));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;LWLockRelease&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;slot&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;io_in_progress_lock);	&lt;span style="color:#75715e"&gt;//函数最后释放LWLock
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;SaveSlotToPath&lt;/code&gt;函数上来就获取&lt;code&gt;LWLockAcquire&lt;/code&gt;，传入slot地址，命名跟等待事件非常类似：&lt;code&gt;io_in_progress_lock&lt;/code&gt;&amp;lt;-&amp;gt;&lt;code&gt; replication_slot_io&lt;/code&gt;，以&lt;code&gt;LW_EXCLUSIVE&lt;/code&gt;模式申请LWLOCK。
在&lt;code&gt;SaveSlotToPath&lt;/code&gt;函数最后有&lt;code&gt;LWLockRelease&lt;/code&gt;释放LWLOCK。
&lt;strong&gt;但是，在所有if判断中，没有任何LWLockRelease，直接return&lt;/strong&gt;！！！&lt;/p&gt;
&lt;p&gt;而pg日志中的输出就是“could not create file” tmppath，说明代码就是走到了以上两个if逻辑里，也就是&lt;strong&gt;写入state.tmp失败&lt;/strong&gt;和&lt;strong&gt;创建state.tmp失败&lt;/strong&gt;的if逻辑中。&lt;/p&gt;
&lt;p&gt;联系pglog中的报错顺序：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;11:36:07：逻辑复制首次报错&amp;quot;could not write to file &amp;ldquo;&amp;ldquo;pg_replslot/pg_lzldb_lzldb_ora_pgdb_pgdb/state.tmp&amp;rdquo;，复制链路挂掉&lt;/li&gt;
&lt;li&gt;11:36:39：checkpointer进程报错&amp;quot;could not create file &amp;ldquo;&amp;ldquo;pg_replslot/pg_lzldb_lzldb_ora_pgdb_pgdb/state.tmp&amp;rdquo;，并于1秒后“complete”，写入0个脏块，0条wal&lt;/li&gt;
&lt;li&gt;11:40:07：逻辑复制再次启动，启动后再无输出&lt;/li&gt;
&lt;li&gt;11:48:03：checkpointer进程再次触发start，后续再无输出，后续再无输出&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;上面有两个逻辑复制和两个checkpointer的日志输出，这里要注意一个很重要的信息：第一次逻辑复制和第二次逻辑复制归属于&lt;em&gt;不同的&lt;/em&gt;walsender进程；第一次checkpoint和第二次checkpoint信息归属于&lt;em&gt;相同的&lt;/em&gt;checkpointer进程。&lt;/p&gt;
&lt;p&gt;从以上信息总结出故障原理：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;逻辑复制因内存问题，写入state.tmp失败，留下一个残存的state.tmp文件&lt;/li&gt;
&lt;li&gt;checkpointer进程因残存的state.tmp文件，在&lt;code&gt;SaveSlotToPath&lt;/code&gt;函数中，以排他模式获得LWLock后进入&lt;code&gt;if (fd &amp;lt; 0)&lt;/code&gt;判断，不释放LWLock直接return&lt;/li&gt;
&lt;li&gt;逻辑复制再次启动，walsender进程在&lt;code&gt;SaveSlotToPath&lt;/code&gt;函数开头申请LWLock，开始无限期等待&lt;/li&gt;
&lt;li&gt;checkpointer进程触发start checkpoint，checkpointer进程在&lt;code&gt;SaveSlotToPath&lt;/code&gt;函数开头申请LWLock，开始无限期等待&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;故障原理理清后答案自然就很清楚：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;walsender和checkpointer为什么hang住了？如上故障原理分析。残存的state.tmp，checkpointer持有LWLock未释放，walsender和checkpointer无限等待。&lt;/li&gt;
&lt;li&gt;walsender和checkpointer是谁阻塞了谁？checkpointer阻塞walsender&lt;/li&gt;
&lt;li&gt;怎么触发的？前一个walsender进程因为内存打满写了state.tmp未清理&lt;/li&gt;
&lt;li&gt;有什么解决方案？强制重启数据库&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;复现
 &lt;div id="复现" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%a4%8d%e7%8e%b0" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;pg逻辑复制知识可参考&lt;a href="https://blog.csdn.net/qq_40687433/article/details/129291207?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171267312516800182785061%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&amp;amp;request_id=171267312516800182785061&amp;amp;biz_id=0&amp;amp;utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-129291207-null-null.nonecase&amp;amp;utm_term=%E9%80%BB%E8%BE%91%E5%A4%8D%E5%88%B6&amp;amp;spm=1018.2226.3001.4450" target="_blank" rel="noreferrer"&gt;pg内功修炼：逻辑复制&lt;/a&gt;，主要使用以下命令：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; pg_create_logical_replication_slot(&lt;span style="color:#e6db74"&gt;&amp;#39;logical_test&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;test_decoding&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pg_recvlogical &lt;span style="color:#f92672"&gt;-&lt;/span&gt;h &lt;span style="color:#ae81ff"&gt;127&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;p &lt;span style="color:#ae81ff"&gt;5558&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;d lzldb &lt;span style="color:#f92672"&gt;-&lt;/span&gt;U lzl &lt;span style="color:#75715e"&gt;--slot=logical_test --start -f recv.sql &amp;amp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;复制槽和逻辑复制链路就OK了：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;postgres&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; pid,usename,xact_start,state_change,wait_event,&lt;span style="color:#66d9ef"&gt;state&lt;/span&gt;,query &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_stat_activity &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;state&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;idle&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;order&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;by&lt;/span&gt; xact_start ;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; usename &lt;span style="color:#f92672"&gt;|&lt;/span&gt; xact_start &lt;span style="color:#f92672"&gt;|&lt;/span&gt; state_change &lt;span style="color:#f92672"&gt;|&lt;/span&gt; wait_event &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; query 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-------+----------+-------------------------------+-------------------------------+---------------------+--------+----------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;59916&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; postgres &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;015534&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;015545&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; pid,usename,xact_start,state_change,wait_event,&lt;span style="color:#66d9ef"&gt;state&lt;/span&gt;,query &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_stat_activity wher
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;e &lt;span style="color:#66d9ef"&gt;state&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;idle&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;order&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;by&lt;/span&gt; xact_start ;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;59791&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzl &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;19&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;566112&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; WalSenderWaitForWAL &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; pg_catalog.set_config(&lt;span style="color:#e6db74"&gt;&amp;#39;search_path&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;postgres&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; pid,usename,application_name,backend_start,&lt;span style="color:#66d9ef"&gt;state&lt;/span&gt;,pg_walfile_name_offset(sent_lsn) sentoffset,pg_walfile_name_offset(write_lsn) writeoffset,pg_walfile_name_offset(flush_lsn) flushoffset &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_stat_replication;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; usename &lt;span style="color:#f92672"&gt;|&lt;/span&gt; application_name &lt;span style="color:#f92672"&gt;|&lt;/span&gt; backend_start &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; sentoffset &lt;span style="color:#f92672"&gt;|&lt;/span&gt; writeoffset &lt;span style="color:#f92672"&gt;|&lt;/span&gt; flushoffset 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-------+---------+------------------+------------------------------+-----------+------------------------------------+------------------------------------+------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;59791&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzl &lt;span style="color:#f92672"&gt;|&lt;/span&gt; pg_recvlogical &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;19&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;56364&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; streaming &lt;span style="color:#f92672"&gt;|&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;000000010000000000000001&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;6612032&lt;/span&gt;) &lt;span style="color:#f92672"&gt;|&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;000000010000000000000001&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;6612032&lt;/span&gt;) &lt;span style="color:#f92672"&gt;|&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;000000010000000000000001&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;6612032&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;因为是state.tmp文件引起的，直接在pg_replslot下面touch&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[postgres&lt;span style="color:#f92672"&gt;@&lt;/span&gt;testhost logical_test]&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt; pwd
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;pgdata&lt;span style="color:#f92672"&gt;/&lt;/span&gt;lzl&lt;span style="color:#f92672"&gt;/&lt;/span&gt;data11&lt;span style="color:#f92672"&gt;/&lt;/span&gt;pg_replslot&lt;span style="color:#f92672"&gt;/&lt;/span&gt;logical_test&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;pg_recvlogical立马报错：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pg_recvlogical: unexpected termination &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; replication stream: ERROR: could &lt;span style="color:#66d9ef"&gt;not&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; file &lt;span style="color:#e6db74"&gt;&amp;#34;pg_replslot/logical_test/state.tmp&amp;#34;&lt;/span&gt;: File &lt;span style="color:#66d9ef"&gt;exists&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;手动执行checkpoint也会hang住&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lzldb&lt;span style="color:#f92672"&gt;=#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;checkpoint&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--hang&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;在看下walsender和会话的状态：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;postgres&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_stat_activity ;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; datid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; datname &lt;span style="color:#f92672"&gt;|&lt;/span&gt; pid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; usesysid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; usename &lt;span style="color:#f92672"&gt;|&lt;/span&gt; application_name &lt;span style="color:#f92672"&gt;|&lt;/span&gt; client_addr &lt;span style="color:#f92672"&gt;|&lt;/span&gt; client_hostname &lt;span style="color:#f92672"&gt;|&lt;/span&gt; client_port &lt;span style="color:#f92672"&gt;|&lt;/span&gt; backend_start &lt;span style="color:#f92672"&gt;|&lt;/span&gt; xact_start &lt;span style="color:#f92672"&gt;|&lt;/span&gt; query_start 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; state_change &lt;span style="color:#f92672"&gt;|&lt;/span&gt; wait_event_type &lt;span style="color:#f92672"&gt;|&lt;/span&gt; wait_event &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; backend_xid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; backend_xmin &lt;span style="color:#f92672"&gt;|&lt;/span&gt; query &lt;span style="color:#f92672"&gt;|&lt;/span&gt; backend_type 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-------+----------+-------+----------+----------+------------------+-------------+-----------------+-------------+-------------------------------+-------------------------------+------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-+&lt;/span&gt;&lt;span style="color:#75715e"&gt;-------------------------------+-----------------+---------------------+--------+-------------+--------------+--------------------------------------------------------+------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;... 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Activity &lt;span style="color:#f92672"&gt;|&lt;/span&gt; LogicalLauncherMain &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; logical replication launcher
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;25&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;55&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;058523&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;checkpoint&lt;/span&gt;; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; client backend
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;16384&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzldb &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;77638&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;16385&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzl &lt;span style="color:#f92672"&gt;|&lt;/span&gt; pg_recvlogical &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;127&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;56928&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;25&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;17&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;495833&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;25&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;17&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;497754&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;25&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;17&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;498329&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; LWLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; replication_slot_io &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; pg_catalog.set_config(&lt;span style="color:#e6db74"&gt;&amp;#39;search_path&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;) &lt;span style="color:#f92672"&gt;|&lt;/span&gt; walsender
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; LWLock &lt;span style="color:#f92672"&gt;|&lt;/span&gt; replication_slot_io &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; checkpointer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;完美复现2个replication_slot_io 等待事件&lt;/p&gt;

&lt;h3 class="relative group"&gt;PG12.3的代码已优化
 &lt;div id="pg123的代码已优化" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#pg123%e7%9a%84%e4%bb%a3%e7%a0%81%e5%b7%b2%e4%bc%98%e5%8c%96" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//这里贴的是15.3，比12.3多一段save_errno
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;SaveSlotToPath&lt;/span&gt;(ReplicationSlot &lt;span style="color:#f92672"&gt;*&lt;/span&gt;slot, &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;char&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;dir, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; elevel)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{	
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	fd &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;OpenTransientFile&lt;/span&gt;(tmppath, O_CREAT &lt;span style="color:#f92672"&gt;|&lt;/span&gt; O_EXCL &lt;span style="color:#f92672"&gt;|&lt;/span&gt; O_WRONLY &lt;span style="color:#f92672"&gt;|&lt;/span&gt; PG_BINARY);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (fd &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * If not an ERROR, then release the lock before returning. In case
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * of an ERROR, the error recovery path automatically releases the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * lock, but no harm in explicitly releasing even in that case. Note
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 * that LWLockRelease() could affect errno.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;		 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;			save_errno &lt;span style="color:#f92672"&gt;=&lt;/span&gt; errno;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;LWLockRelease&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;slot&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;io_in_progress_lock);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		errno &lt;span style="color:#f92672"&gt;=&lt;/span&gt; save_errno;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;ereport&lt;/span&gt;(elevel,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				(&lt;span style="color:#a6e22e"&gt;errcode_for_file_access&lt;/span&gt;(),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				 &lt;span style="color:#a6e22e"&gt;errmsg&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;could not create file &lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;%s&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;: %m&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;						tmppath)));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;LWLockRelease&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;slot&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;io_in_progress_lock);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}	
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;在&lt;strong&gt;每一个 if中&lt;/strong&gt;，在都会先运行LWLockRelease，然后再return。这样就不会某些场景下LWLock不释放的逻辑漏洞了，代码明显更为健壮。&lt;/p&gt;

&lt;h3 class="relative group"&gt;解决办法分析
 &lt;div id="解决办法分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%a7%a3%e5%86%b3%e5%8a%9e%e6%b3%95%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;因为state.tmp文件只是诱因，LWLOCK已经持有了，删除state.tmp不会解决这个问题。
因为真正持有LW_LOCK的人是checkpointer，所以重启复制链路或者kill下游都是也是没有用的。
因为是checkpointer进程不能直接kill，目前这个状态除了重启没有好的解决办法，而且只有&lt;strong&gt;强制重启&lt;/strong&gt;进行实例恢复，正常关库因为checkpoint阻塞是关不了的···
最后，终极解决办法当然是升级到PG12.3以上。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;（另外，我也试了下gdb调用LWLockRelease（LWLock的地址pstack已经输出了），直接把测试环境库搞挂了，所以就不推荐gdb了）&lt;/em&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;总结
 &lt;div id="总结" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%80%bb%e7%bb%93" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;PG在近期的版本中最为重要的特性提升之一就是逻辑复制，早期的PG的逻辑复制确实是存在很多问题，坑多。PG这种&lt;a href="https://blog.csdn.net/qq_40687433/article/details/136405862?spm=1001.2014.3001.5501" target="_blank" rel="noreferrer"&gt;大包大揽的逻辑复制思路&lt;/a&gt;很有技术创新的精神，而且也能看到社区孜孜不倦地对逻辑复制的完善和加强，几乎每个小版本都能搜到逻辑复制的许多更新。这个案例就是一个现实的例子，逻辑复制的代码明显越来越健壮。
逻辑复制的知识点其实挺多的，最后推荐一波之前的文章：&lt;a href="https://blog.csdn.net/qq_40687433/article/details/129291207?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171267312516800182785061%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&amp;amp;request_id=171267312516800182785061&amp;amp;biz_id=0&amp;amp;utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-129291207-null-null.nonecase&amp;amp;utm_term=%E9%80%BB%E8%BE%91%E5%A4%8D%E5%88%B6&amp;amp;spm=1018.2226.3001.4450" target="_blank" rel="noreferrer"&gt;pg内功修炼：逻辑复制&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>分区权限问题导致执行计划不正确</title><link>https://lastdba.com/2024/08/12/%E5%88%86%E5%8C%BA%E6%9D%83%E9%99%90%E9%97%AE%E9%A2%98%E5%AF%BC%E8%87%B4%E6%89%A7%E8%A1%8C%E8%AE%A1%E5%88%92%E4%B8%8D%E6%AD%A3%E7%A1%AE/</link><pubDate>Mon, 12 Aug 2024 00:00:00 +0000</pubDate><guid>https://lastdba.com/2024/08/12/%E5%88%86%E5%8C%BA%E6%9D%83%E9%99%90%E9%97%AE%E9%A2%98%E5%AF%BC%E8%87%B4%E6%89%A7%E8%A1%8C%E8%AE%A1%E5%88%92%E4%B8%8D%E6%AD%A3%E7%A1%AE/</guid><description>&lt;h2 class="relative group"&gt;问题现象
 &lt;div id="问题现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;业务昨晚对sql进行了更新，之前没有DATE_CREATED字段（是分区键），跑的很快。发版后加了分区字段，本身是为了减少分区数量的访问，但是加了以后UPDATE执行却变慢了。
before：&lt;/p&gt;</description><content:encoded>
&lt;h2 class="relative group"&gt;问题现象
 &lt;div id="问题现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;业务昨晚对sql进行了更新，之前没有DATE_CREATED字段（是分区键），跑的很快。发版后加了分区字段，本身是为了减少分区数量的访问，但是加了以后UPDATE执行却变慢了。
before：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;update&lt;/span&gt; TABLE_RECORD
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; IS_DELETED &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;, DATE_UPDATED &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;LOCALTIMESTAMP&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;WHERE&lt;/span&gt; APPL_NO &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; IS_DELETED &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;after：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;update&lt;/span&gt; TABLE_RECORD
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; IS_DELETED &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;, DATE_UPDATED &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;LOCALTIMESTAMP&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;WHERE&lt;/span&gt; APPL_NO &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; IS_DELETED &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; DATE_CREATED &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; interval &lt;span style="color:#e6db74"&gt;&amp;#39;31&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; DATE_CREATED &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;发版前访问时间是毫秒级，发版后访问时间是10s，sql运行频繁，业务不可接受。&lt;/p&gt;

&lt;h2 class="relative group"&gt;问题分析
 &lt;div id="问题分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;执行计划看上去是正确的
 &lt;div id="执行计划看上去是正确的" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%89%a7%e8%a1%8c%e8%ae%a1%e5%88%92%e7%9c%8b%e4%b8%8a%e5%8e%bb%e6%98%af%e6%ad%a3%e7%a1%ae%e7%9a%84" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;表结构如下&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;##&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;d&lt;span style="color:#f92672"&gt;+&lt;/span&gt; TABLE_RECORD
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Partitioned &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;public.TABLE_RECORD&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Column&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Type&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Collation&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Nullable&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Default&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Storage&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Stats target &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Description 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--------------------------------+-----------------------------+-----------+----------+---------------------------------------------------+----------+--------------+--------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; id_TABLE_RECORD &lt;span style="color:#f92672"&gt;|&lt;/span&gt; character varying(&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;) &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;not&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; nextval(&lt;span style="color:#e6db74"&gt;&amp;#39;seq_TABLE_RECORD&amp;#39;&lt;/span&gt;::regclass) &lt;span style="color:#f92672"&gt;|&lt;/span&gt; extended &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; appl_no &lt;span style="color:#f92672"&gt;|&lt;/span&gt; character varying(&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;) &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; extended &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; r_appl_no &lt;span style="color:#f92672"&gt;|&lt;/span&gt; character varying(&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;) &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; extended &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; created_by &lt;span style="color:#f92672"&gt;|&lt;/span&gt; character varying(&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;) &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;not&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;sys&amp;#39;&lt;/span&gt;::character varying &lt;span style="color:#f92672"&gt;|&lt;/span&gt; extended &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; date_created &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;not&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; now() &lt;span style="color:#f92672"&gt;|&lt;/span&gt; plain &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; updated_by &lt;span style="color:#f92672"&gt;|&lt;/span&gt; character varying(&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;) &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;not&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;sys&amp;#39;&lt;/span&gt;::character varying &lt;span style="color:#f92672"&gt;|&lt;/span&gt; extended &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; date_updated &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;not&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; now() &lt;span style="color:#f92672"&gt;|&lt;/span&gt; plain &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Partition &lt;span style="color:#66d9ef"&gt;key&lt;/span&gt;: RANGE (date_created)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Indexes:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;date_TABLE_RECORD&amp;#34;&lt;/span&gt; btree (date_created)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;idx_dateupdated&amp;#34;&lt;/span&gt; btree (date_updated)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;idx_applnodeleted&amp;#34;&lt;/span&gt; btree (appl_no, is_deleted)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;nk_TABLE_RECORD&amp;#34;&lt;/span&gt; btree (appl_no)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Partitions: TABLE_RECORD_202211 &lt;span style="color:#66d9ef"&gt;FOR&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;VALUES&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2022-11-01 00:00:00&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;TO&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2022-12-01 00:00:00&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; TABLE_RECORD_202303 &lt;span style="color:#66d9ef"&gt;FOR&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;VALUES&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-03-01 00:00:00&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;TO&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-04-01 00:00:00&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; TABLE_RECORD_202304 &lt;span style="color:#66d9ef"&gt;FOR&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;VALUES&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-04-01 00:00:00&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;TO&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-05-01 00:00:00&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; TABLE_RECORD_202305 &lt;span style="color:#66d9ef"&gt;FOR&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;VALUES&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-05-01 00:00:00&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;TO&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-06-01 00:00:00&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; TABLE_RECORD_202306 &lt;span style="color:#66d9ef"&gt;FOR&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;VALUES&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-06-01 00:00:00&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;TO&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-07-01 00:00:00&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; TABLE_RECORD_202512 &lt;span style="color:#66d9ef"&gt;FOR&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;VALUES&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2025-12-01 00:00:00&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;TO&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2026-01-01 00:00:00&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; TABLE_RECORD_other &lt;span style="color:#66d9ef"&gt;DEFAULT&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这个sql会访问近2个月的分区，这2个分区都是有数据的，上面的update只会更新一条数据。
刚开始分析问题非常困惑，因为我们explain的时候，执行计划是没有问题的
explain分区扫描信息：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; TABLE_RECORD_202302_date_created_idx &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; TABLE_RECORD_202302 TABLE_RECORD_4 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;44&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;47&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;485&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((date_created &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; (now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;31 days&amp;#39;&lt;/span&gt;::interval &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt;)) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (date_created &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now()))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (((appl_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;LZLMATH20230132302302&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((is_deleted)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; TABLE_RECORD_202303_date_created_idx &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; TABLE_RECORD_202303 TABLE_RECORD_5 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;44&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;47&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;482&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((date_created &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; (now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;31 days&amp;#39;&lt;/span&gt;::interval &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt;)) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (date_created &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now()))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (((appl_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;LZLMATH20230132302302&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((is_deleted)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; TABLE_RECORD_202304_date_created_idx &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; TABLE_RECORD_202304 TABLE_RECORD_6 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;44&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;47&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;481&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((date_created &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; (now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;31 days&amp;#39;&lt;/span&gt;::interval &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt;)) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (date_created &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now()))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (((appl_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;LZLMATH20230132302302&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((is_deleted)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_applnodeleted_25 &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; TABLE_RECORD_202305 TABLE_RECORD_7 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;49&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;483&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (((appl_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;LZLMATH20230132302302&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((is_deleted)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((date_created &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now()) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (date_created &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; (now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;31 days&amp;#39;&lt;/span&gt;::interval &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_applnodeleted_14 &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; TABLE_RECORD_202306 TABLE_RECORD_8 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;45&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;11&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;485&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (((appl_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;LZLMATH20230132302302&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((is_deleted)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((date_created &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now()) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (date_created &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; (now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;31 days&amp;#39;&lt;/span&gt;::interval &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_applnodeleted_38 &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; TABLE_RECORD_202307 TABLE_RECORD_9 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;17&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3502&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (((appl_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;LZLMATH20230132302302&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((is_deleted)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((date_created &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now()) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (date_created &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; (now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;31 days&amp;#39;&lt;/span&gt;::interval &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_applnodeleted_1 &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; TABLE_RECORD_202308 TABLE_RECORD_10 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;17&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3502&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;分区数据分布：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;),tableoid::regclass &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; TABLE_RECORD &lt;span style="color:#66d9ef"&gt;group&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;by&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; tableoid 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-------+---------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;56558&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; TABLE_RECORD_202303
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;4436&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; TABLE_RECORD_202211
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;6929&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; TABLE_RECORD_202306
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;945&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; TABLE_RECORD_202305
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;1413&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; TABLE_RECORD_202304
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;5499&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; TABLE_RECORD_202212
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;1486&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; TABLE_RECORD_202301
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;4722&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; TABLE_RECORD_202302&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;执行计划看上去对不同的分区访问了不同的索引
date_TABLE_RECORD：分区键上的索引
idx_applnodeleted：appl_no, is_deleted组合索引
实际上sql可以通过DATE_CREATED近31天数据字段裁剪分区。但是如果在用这个字段的索引，那就没有任何过滤性了。而appl_no, is_deleted在分区中过滤性较好，真正的执行计划应该选择 idx_applnodeleted组合索引。
上面的explain执行计划虽然不是真正的执行计划，但是能看到5、6月份的走的索引是没有问题的，走的是appl_no, is_deleted组合索引。
查看真实的执行计划会执行sql，所以把update改成select，查看真实的执行计划&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt;,buffers,timing,&lt;span style="color:#66d9ef"&gt;verbose&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; TABLE_RECORD &lt;span style="color:#66d9ef"&gt;WHERE&lt;/span&gt; APPL_NO &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;LZLMATH20230132302302&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; IS_DELETED &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; DATE_CREATED &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; interval &lt;span style="color:#e6db74"&gt;&amp;#39;31&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; DATE_CREATED &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now() ;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Aggregate&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;266&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;266&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;565&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;566&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Output&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;48&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Append (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;265&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;95&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;388&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;558&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;48&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Subplans Removed: &lt;span style="color:#ae81ff"&gt;37&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_applnodeleted_25 &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt;.TABLE_RECORD_202305 TABLE_RECORD_1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;39&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;059&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;059&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (((TABLE_RECORD_1.appl_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;LZLMATH20230132302302&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((TABLE_RECORD_1.is_deleted)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((TABLE_RECORD_1.date_created &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now()) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (TABLE_RECORD_1.date_created &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; (now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;31 days&amp;#39;&lt;/span&gt;::interval &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_applnodeleted_14 &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt;.TABLE_RECORD_202306 TABLE_RECORD_2 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;52&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;17&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;328&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;498&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (((TABLE_RECORD_2.appl_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;LZLMATH20230132302302&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((TABLE_RECORD_2.is_deleted)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((TABLE_RECORD_2.date_created &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now()) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (TABLE_RECORD_2.date_created &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; (now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;31 days&amp;#39;&lt;/span&gt;::interval &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;45&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Planning:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5867&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Planning Time: &lt;span style="color:#ae81ff"&gt;17&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;195&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Execution Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;654&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;select只访问了5月和6月两个分区，说明分区裁剪没问题；两个分区都是idx_applnodeleted索引，所以索引选择也没问题。
直接执行select语句，执行时间是ms级。&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;##&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; TABLE_RECORD &lt;span style="color:#66d9ef"&gt;WHERE&lt;/span&gt; APPL_NO &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;LZLMATH20230132302302&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; IS_DELETED &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; DATE_CREATED &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; interval &lt;span style="color:#e6db74"&gt;&amp;#39;31&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; DATE_CREATED &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now() ;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;row&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Time: &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;946&lt;/span&gt; ms&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;分析到这里，看上去执行计划正常，执行时间正常&lt;/p&gt;

&lt;h3 class="relative group"&gt;业务sql仍然缓慢
 &lt;div id="业务sql仍然缓慢" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%b8%9a%e5%8a%a1sql%e4%bb%8d%e7%84%b6%e7%bc%93%e6%85%a2" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;但是，postgresql日志中仍然能抓到慢sql，update执行了10s&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2023&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;06&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;06&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;45&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;077&lt;/span&gt; CST,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldbopr&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;116286&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;30.88.78.90:51871&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;649&lt;/span&gt;cdebf.&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;c63e,&lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;UPDATE&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2023&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;06&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;39&lt;/span&gt; CST,&lt;span style="color:#ae81ff"&gt;759&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;12440291&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;4002354803&lt;/span&gt;,LOG,&lt;span style="color:#ae81ff"&gt;00000&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;duration: 10287.105 ms &amp;#34;&lt;/span&gt; plan:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Query Text: &lt;span style="color:#66d9ef"&gt;update&lt;/span&gt; TABLE_RECORD
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; IS_DELETED &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;, DATE_UPDATED &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;LOCALTIMESTAMP&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;WHERE&lt;/span&gt; APPL_NO &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; IS_DELETED &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; DATE_CREATED &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; interval &lt;span style="color:#e6db74"&gt;&amp;#39;31&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; DATE_CREATED &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Update&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; TABLE_RECORD (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;203&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;79&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;39&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2960&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Update&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; TABLE_RECORD_202211 TABLE_RECORD_1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; TABLE_RECORD_202304_date_created_idx &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; TABLE_RECORD_202304 TABLE_RECORD_6 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;44&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;47&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;481&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((date_created &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; (now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;31 days&amp;#39;&lt;/span&gt;::interval &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt;)) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (date_created &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now()))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (((appl_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;LZLMATH20230132302302&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((is_deleted)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; TABLE_RECORD_202305_date_created_idx &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; TABLE_RECORD_202305 TABLE_RECORD_7 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;44&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;47&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;483&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((date_created &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; (now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;31 days&amp;#39;&lt;/span&gt;::interval &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt;)) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (date_created &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now()))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (((appl_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;LZLMATH20230132302302&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((is_deleted)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; TABLE_RECORD_202306_date_created_idx &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; TABLE_RECORD_202306 TABLE_RECORD_8 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;44&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;47&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;485&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((date_created &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; (now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;31 days&amp;#39;&lt;/span&gt;::interval &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt;)) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (date_created &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now()))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (((appl_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;LZLMATH20230132302302&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((is_deleted)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_applnodeleted_38 &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; TABLE_RECORD_202307 TABLE_RECORD_9 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;17&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3502&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (((appl_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;LZLMATH20230132302302&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((is_deleted)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((date_created &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now()) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (date_created &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; (now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;31 days&amp;#39;&lt;/span&gt;::interval &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;5、6月分区还是用的date_created分区键上的索引，执行计划只估算了1行，实际上这2个分区实际上都有百万行数据。
分析到这里就非常困惑，优化器本身可以走到更好的索引，explain也看到走到了那个索引，但是业务sql就是没有走正确的索引。&lt;/p&gt;

&lt;h3 class="relative group"&gt;更新统计信息
 &lt;div id="更新统计信息" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%9b%b4%e6%96%b0%e7%bb%9f%e8%ae%a1%e4%bf%a1%e6%81%af" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;因为是pgsql执行计划的问题，首先都会想到收集统计信息
问题发生后，收集了分区表父表和子表的统计信息，并且担心会话缓存了执行计划（plan_cache_mode=auto），将统计信息收集时间之前的会话全部kill。
日志仍然显示sql执行10s，说明不是统计信息的问题。
做到这里问题仍然没有解决，似乎已经黔驴技穷了。&lt;/p&gt;

&lt;h2 class="relative group"&gt;问题根因
 &lt;div id="问题根因" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e6%a0%b9%e5%9b%a0" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;前面分析执行计划的时候，dba explain的执行计划与应用的执行计划不一致，不过我们都是用postgres超级用户执行的。切换为应用用户再次explain执行，执行计划结果与日志中的执行计划一致！
因为之前出现过原生分区表权限问题，导致执行计划异常的情况。所以立即检查分区表分区的权限
父表权限&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;##&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;dp&lt;span style="color:#f92672"&gt;+&lt;/span&gt; TABLE_RECORD
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Access&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;privileges&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Schema&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Name &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Type&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Access&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;privileges&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Column&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;privileges&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Policies 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--------+--------------------------+-------------------+-------------------------------------+-------------------+----------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; TABLE_RECORD &lt;span style="color:#f92672"&gt;|&lt;/span&gt; partitioned &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzldbdata&lt;span style="color:#f92672"&gt;=&lt;/span&gt;arwdDxt&lt;span style="color:#f92672"&gt;/&lt;/span&gt;lzldbdata &lt;span style="color:#f92672"&gt;+|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; r_lzldbdata_qry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;r&lt;span style="color:#f92672"&gt;/&lt;/span&gt;lzldbdata &lt;span style="color:#f92672"&gt;+|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; r_lzldbdata_dml&lt;span style="color:#f92672"&gt;=&lt;/span&gt;arwd&lt;span style="color:#f92672"&gt;/&lt;/span&gt;lzldbdata &lt;span style="color:#f92672"&gt;+|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;row&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;子表权限&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;##&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;dp&lt;span style="color:#f92672"&gt;+&lt;/span&gt; TABLE_RECORD_202505
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Access&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;privileges&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Schema&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Name &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Type&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Access&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;privileges&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Column&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;privileges&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Policies 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--------+---------------------------------+-------+------------------------------------+-------------------+----------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; TABLE_RECORD_202505 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzldbdata&lt;span style="color:#f92672"&gt;=&lt;/span&gt;arwdDxt&lt;span style="color:#f92672"&gt;/&lt;/span&gt;lzldbdata &lt;span style="color:#f92672"&gt;+|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;分区权限少了r_lzldbdata_dml这个角色的,这个角色是授权给业务用户的。
立即执行授权，问题解决&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;grant&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt;,&lt;span style="color:#66d9ef"&gt;update&lt;/span&gt;,&lt;span style="color:#66d9ef"&gt;delete&lt;/span&gt;,&lt;span style="color:#66d9ef"&gt;insert&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; TABLE_RECORD_202305 &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; r_lzldbdata_dml;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;grant&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt;,&lt;span style="color:#66d9ef"&gt;update&lt;/span&gt;,&lt;span style="color:#66d9ef"&gt;delete&lt;/span&gt;,&lt;span style="color:#66d9ef"&gt;insert&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; TABLE_RECORD_202306 &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; r_lzldbdata_dml;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;再次用opr用户explain，执行计划正确，5、6月走了正常的索引
&lt;code&gt;\c - lzldbopr&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; TABLE_RECORD_202303_date_created_idx &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; TABLE_RECORD_202303 TABLE_RECORD_5 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;44&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;47&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;482&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((date_created &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; (now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;31 days&amp;#39;&lt;/span&gt;::interval &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt;)) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (date_created &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now()))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (((appl_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;LZLMATH20230132302302&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((is_deleted)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; TABLE_RECORD_202304_date_created_idx &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; TABLE_RECORD_202304 TABLE_RECORD_6 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;44&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;47&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;481&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((date_created &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; (now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;31 days&amp;#39;&lt;/span&gt;::interval &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt;)) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (date_created &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now()))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (((appl_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;LZLMATH20230132302302&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((is_deleted)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_applnodeleted_25 &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; TABLE_RECORD_202305 TABLE_RECORD_7 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;39&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;483&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (((appl_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;LZLMATH20230132302302&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((is_deleted)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((date_created &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now()) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (date_created &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; (now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;31 days&amp;#39;&lt;/span&gt;::interval &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_applnodeleted_14 &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; TABLE_RECORD_202306 TABLE_RECORD_8 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;57&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;17&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;485&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (((appl_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;LZLMATH20230132302302&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((is_deleted)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((date_created &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now()) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (date_created &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; (now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;31 days&amp;#39;&lt;/span&gt;::interval &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_applnodeleted_38 &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; TABLE_RECORD_202307 TABLE_RECORD_9 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;17&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3502&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (((appl_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;LZLMATH20230132302302&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((is_deleted)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((date_created &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now()) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (date_created &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; (now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;31 days&amp;#39;&lt;/span&gt;::interval &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_applnodeleted_1 &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; TABLE_RECORD_202308 TABLE_RECORD_10 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;17&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3502&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (((appl_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;LZLMATH20230132302302&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((is_deleted)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((date_created &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now()) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (date_created &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; (now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;31 days&amp;#39;&lt;/span&gt;::interval &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt;)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;pg日志上也未再观察到慢update语句。&lt;/p&gt;

&lt;h2 class="relative group"&gt;测试（没复现）
 &lt;div id="测试没复现" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%b5%8b%e8%af%95%e6%b2%a1%e5%a4%8d%e7%8e%b0" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;初始化建表脚本&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--切换非超级用户
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; lzldbdata
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--create table
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;CREATE&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;TABLE&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PUBLIC&lt;/span&gt;.LZLPARTITION
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; APPL_NO varchar(&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	IS_DELETED varchar(&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; DATE_CREATED &lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NOT&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;DEFAULT&lt;/span&gt; now(),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; DATE_UPDATED &lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NOT&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;DEFAULT&lt;/span&gt; now()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;) PARTITION &lt;span style="color:#66d9ef"&gt;BY&lt;/span&gt; RANGE(DATE_CREATED);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--indexes
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; DATE_LZLPARTITION &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PUBLIC&lt;/span&gt;.LZLPARTITION (DATE_CREATED);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; NK_LZLPARTITION &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PUBLIC&lt;/span&gt;.LZLPARTITION (APPL_NO);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--privs
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;GRANT&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ON&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;TABLE&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt;.LZLPARTITION &lt;span style="color:#66d9ef"&gt;TO&lt;/span&gt; r_lzldbdata_qry;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;GRANT&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt;,&lt;span style="color:#66d9ef"&gt;INSERT&lt;/span&gt;,&lt;span style="color:#66d9ef"&gt;UPDATE&lt;/span&gt;,&lt;span style="color:#66d9ef"&gt;DELETE&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ON&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;TABLE&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt;.LZLPARTITION &lt;span style="color:#66d9ef"&gt;TO&lt;/span&gt; r_lzldbdata_dml;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--partition
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; LZLPARTITION_202301 partition &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; LZLPARTITION &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;values&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-01-01 00:00:00&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-02-01 00:00:00&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; LZLPARTITION_202302 partition &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; LZLPARTITION &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;values&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-02-01 00:00:00&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-03-01 00:00:00&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; LZLPARTITION_202303 partition &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; LZLPARTITION &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;values&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-03-01 00:00:00&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-04-01 00:00:00&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; LZLPARTITION_202304 partition &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; LZLPARTITION &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;values&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-04-01 00:00:00&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-05-01 00:00:00&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; LZLPARTITION_202305 partition &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; LZLPARTITION &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;values&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-05-01 00:00:00&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-06-01 00:00:00&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; LZLPARTITION_202306 partition &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; LZLPARTITION &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;values&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-06-01 00:00:00&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-07-01 00:00:00&amp;#39;&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;生成数据：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;insert&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;into&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt;.LZLPARTITION
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; n &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;N&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; to_char(to_date(&lt;span style="color:#e6db74"&gt;&amp;#39;2023-01-01&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;YYYY-MM-DD&amp;#39;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;+&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt; n &lt;span style="color:#f92672"&gt;||&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39; minute&amp;#39;&lt;/span&gt;) ::interval, &lt;span style="color:#e6db74"&gt;&amp;#39;YYYY-MM-DD&amp;#39;&lt;/span&gt;)::&lt;span style="color:#e6db74"&gt;&amp;#34;date&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; now()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;from&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; generate_series(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;300000&lt;/span&gt;) n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;数据分布：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;),tableoid::regclass &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzlpartition &lt;span style="color:#66d9ef"&gt;group&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;by&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; tableoid 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-------+---------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;44640&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzlpartition_202301
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;40320&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzlpartition_202302
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;44640&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzlpartition_202303
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;43200&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzlpartition_202304
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;44640&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzlpartition_202305
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;43200&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzlpartition_202306
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;39361&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzlpartition_202307&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;权限未继承：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;##&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;dp&lt;span style="color:#f92672"&gt;+&lt;/span&gt; lzlpartition
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Access&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;privileges&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Schema&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Name &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Type&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Access&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;privileges&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Column&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;privileges&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Policies 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--------+--------------+-------------------+-------------------------------------+-------------------+----------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzlpartition &lt;span style="color:#f92672"&gt;|&lt;/span&gt; partitioned &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzldbdata&lt;span style="color:#f92672"&gt;=&lt;/span&gt;arwdDxt&lt;span style="color:#f92672"&gt;/&lt;/span&gt;lzldbdata &lt;span style="color:#f92672"&gt;+|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; r_lzldbdata_qry&lt;span style="color:#f92672"&gt;=&lt;/span&gt;r&lt;span style="color:#f92672"&gt;/&lt;/span&gt;lzldbdata &lt;span style="color:#f92672"&gt;+|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; r_lzldbdata_dml&lt;span style="color:#f92672"&gt;=&lt;/span&gt;arwd&lt;span style="color:#f92672"&gt;/&lt;/span&gt;lzldbdata &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;##&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;dp&lt;span style="color:#f92672"&gt;+&lt;/span&gt; lzlpartition_202306
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Access&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;privileges&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Schema&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Name &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Type&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Access&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;privileges&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Column&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;privileges&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Policies 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--------+---------------------+-------+-------------------+-------------------+----------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzlpartition_202306 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;执行计划（正确）：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;count&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzlpartition &lt;span style="color:#66d9ef"&gt;WHERE&lt;/span&gt; APPL_NO &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;217450&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; IS_DELETED &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;N&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; DATE_CREATED &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; interval &lt;span style="color:#e6db74"&gt;&amp;#39;31&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; DATE_CREATED &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--------------------------------------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Aggregate&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;36&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;76&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;36&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;77&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Append (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;29&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;36&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;74&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;7&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Subplans Removed: &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; lzlpartition_202305_appl_no_idx &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzlpartition_202305 lzlpartition_1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;19&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((appl_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;217450&amp;#39;&lt;/span&gt;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (((is_deleted)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (date_created &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now()) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (date_created &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; (now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;31 days&amp;#39;&lt;/span&gt;::interval &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; lzlpartition_202306_appl_no_idx &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzlpartition_202306 lzlpartition_2 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;19&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((appl_no)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;217450&amp;#39;&lt;/span&gt;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (((is_deleted)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (date_created &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; now()) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (date_created &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; (now() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;31 days&amp;#39;&lt;/span&gt;::interval &lt;span style="color:#66d9ef"&gt;day&lt;/span&gt;)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;权限仍然没有继承，其实测了其他pg版本也是这样的，看上去是一个通用行为。
但是就算这样也没有复现出来，测试结果走了正确的索引，没有像生产环境那样走错误的索引。&lt;/p&gt;

&lt;h2 class="relative group"&gt;问题总结
 &lt;div id="问题总结" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e6%80%bb%e7%bb%93" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;因为我们收集了统计信息并kill了会话，不应该是缓存执行计划的问题。执行了grant后，分区执行计划立即正确（甚至grant一个分区，对一个分区），所以比较确认是分区权限导致分区执行计划异常的。分析和处理问题的过程总结如下&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;切换应用用户查看执行计划。直接用超级用户登陆查看执行计划是通用做法，但是查看到的执行计划还是不对的。&lt;/li&gt;
&lt;li&gt;分区表子表的权限问题。根因是postgresql分区表子表上的权限与父表不一致，导致执行计划异常，也就是说权限问题影响了pg的执行计划。&lt;/li&gt;
&lt;li&gt;该问题不好复现，非常非常偶发。&lt;/li&gt;
&lt;li&gt;权限导致执行计划异常这个问题非常隐蔽，不好定位。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;想深入讨论2个问题&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;权限问题不应该影响执行计划。为什么权限会影响执行计划？&lt;/li&gt;
&lt;li&gt;子表权限与父表不一致。为什么子表没有全部继承父表权限？
已提交BUG看看官方咋说&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title>花式分析一个5M的SQL占用70GB内存</title><link>https://lastdba.com/2024/08/12/%E8%8A%B1%E5%BC%8F%E5%88%86%E6%9E%90%E4%B8%80%E4%B8%AA5m%E7%9A%84sql%E5%8D%A0%E7%94%A870gb%E5%86%85%E5%AD%98/</link><pubDate>Mon, 12 Aug 2024 00:00:00 +0000</pubDate><guid>https://lastdba.com/2024/08/12/%E8%8A%B1%E5%BC%8F%E5%88%86%E6%9E%90%E4%B8%80%E4%B8%AA5m%E7%9A%84sql%E5%8D%A0%E7%94%A870gb%E5%86%85%E5%AD%98/</guid><description>&lt;h3 class="relative group"&gt;进程内存分析
 &lt;div id="进程内存分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%bf%9b%e7%a8%8b%e5%86%85%e5%ad%98%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;WAL writer process (PID 66902) was terminated by signal 6: Aborted&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;postmaster&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;从日志中找到被kill的postmaster进程66902&lt;/p&gt;</description><content:encoded>
&lt;h3 class="relative group"&gt;进程内存分析
 &lt;div id="进程内存分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%bf%9b%e7%a8%8b%e5%86%85%e5%ad%98%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;WAL writer process (PID 66902) was terminated by signal 6: Aborted&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;postmaster&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;从日志中找到被kill的postmaster进程66902&lt;/p&gt;
&lt;p&gt;到osw中找进程消耗的内存。由于top没有PPID，PS没有USS信息，所以要两个一起看&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;USER PID PPID PRI %CPU %MEM VSZ RSS WCHAN S STARTED TIME COMMAND
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;postgres &lt;span style="color:#ae81ff"&gt;211276&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;66478&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;19&lt;/span&gt; 8.7 10.6 &lt;span style="color:#ae81ff"&gt;57488380&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;56389972&lt;/span&gt; - R 17:13:03 00:02:47 postgres: BIND
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;postgres &lt;span style="color:#ae81ff"&gt;211277&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;66478&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;19&lt;/span&gt; 7.8 9.6 &lt;span style="color:#ae81ff"&gt;52294700&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;51127480&lt;/span&gt; - R 17:13:03 00:02:31 postgres: BIND
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;postgres &lt;span style="color:#ae81ff"&gt;222749&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;66478&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;19&lt;/span&gt; 22.7 9.3 &lt;span style="color:#ae81ff"&gt;51320000&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;49073368&lt;/span&gt; - R 17:35:33 00:02:09 postgres: BIND
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;postgres &lt;span style="color:#ae81ff"&gt;39513&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;66478&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;19&lt;/span&gt; 2.9 6.8 &lt;span style="color:#ae81ff"&gt;38651084&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;36354736&lt;/span&gt; ep_poll S 16:13:03 00:02:43 postgres: idle&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;通过PPID找个backend消耗较高的进程，比如211276进程进行进一步分析&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;postgres@lzl&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ zcat /osw/oswtop/toposw.dat.gz |grep &lt;span style="color:#ae81ff"&gt;211276&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;211276&lt;/span&gt; postgres &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3271756&lt;/span&gt; 1.1g 1.1g S 7.3 0.2 0:03.93 postgres
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;211276&lt;/span&gt; postgres &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3291784&lt;/span&gt; 1.3g 1.2g R 96.4 0.2 0:11.87 postgres
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;211276&lt;/span&gt; postgres &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7369628&lt;/span&gt; 6.0g 2.1g R 100.0 1.2 0:46.58 postgres
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;211276&lt;/span&gt; postgres &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 17.0g 15.9g 2.1g R 100.0 3.2 1:16.70 postgres
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;211276&lt;/span&gt; postgres &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 28.8g 27.7g 2.1g R 100.0 5.5 1:46.82 postgres
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;211276&lt;/span&gt; postgres &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 41.4g 40.4g 2.1g R 100.0 8.0 2:16.99 postgres
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;211276&lt;/span&gt; postgres &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 54.7g 53.7g 2.1g R 88.8 10.7 2:47.60 postgres
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;211276&lt;/span&gt; postgres &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 66.5g 64.9g 2.1g R 34.7 12.9 3:22.76 postgres
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;211276&lt;/span&gt; postgres &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 71.0g 68.2g 2.1g R 99.1 13.6 3:52.94 postgres
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;211276&lt;/span&gt; postgres &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 74.9g 71.2g 2.1g R 100.0 14.2 4:23.05 postgres
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;211276&lt;/span&gt; postgres &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; R 100.0 0.0 4:45.65 postgres&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;top可以通过RES-SHR=USS来判断进程私有内存的消耗。211276进程的内存几分钟内暴涨到70g挂掉，并且都是进程私有内存消耗&lt;/p&gt;

&lt;h3 class="relative group"&gt;sql分析
 &lt;div id="sql分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#sql%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;PG日志中一个5M的SQL，包含5000+个union all，3万个变量
执行计划长达7W行&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Append (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;218196&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;51&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;218216&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;28&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1318&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1628&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; InitPlan &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;returns&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; table1 &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; table1nfo (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;29&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;31&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;40&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((col1)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;xxx&amp;#39;&lt;/span&gt;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((colcolcol)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;xxx&amp;#39;&lt;/span&gt;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; InitPlan &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;returns&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; table1 &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; table1nfo table1nfo_1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;29&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;31&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;40&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((col1)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;xxx&amp;#39;&lt;/span&gt;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((colcolcol)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;xxx&amp;#39;&lt;/span&gt;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; InitPlan &lt;span style="color:#ae81ff"&gt;10544&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;returns&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10543&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Aggregate&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;58&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;59&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; table2 &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; table2col t_1317 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;56&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;58&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;19&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((ididid)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;xxx&amp;#39;&lt;/span&gt;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((idididid)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;::text)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;执行计划结构非常简单，1w个子计划查数据，最后append结果。&lt;/p&gt;
&lt;p&gt;就是这么个拼接怪SQL把backend进程打到70GB。其实不用深入分析也知道，这个sql是有问题的，把union all减少，问题应该是可以修复的（事实上就是这样）。但是如果仔细想想，这里有很多问题可以深入分析：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;为什么5M的SQL可以把内存打到70GB？&lt;/li&gt;
&lt;li&gt;数据本身跟内存有关系吗？是因为返回数据过多导致的吗？&lt;/li&gt;
&lt;li&gt;是解析数据缓存大，还是因为执行计划缓存数据大？&lt;/li&gt;
&lt;li&gt;work_mem明明不大，为什么没有起到限制operation内存的效果？&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 class="relative group"&gt;初步分析
 &lt;div id="初步分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%88%9d%e6%ad%a5%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;如果一个5M的sql缓存在backend中，里面至少应该包含所要的元数据、SQL解析数据、执行计划缓存信息
我们之前碰到过几十万个表/分区表的元数据缓存导致relcache过大，从而导致backend内存很大。而这个库的表不多，初步可以排除relcache问题（后续查看dump内存可以确认排除）。
SQL解析数据理应不会太多，5M的sql解析出来至少不应该是70G。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;work_mem的内存限制and more：&lt;/strong&gt;
work_mem只限制每个operation的sort（可以用到sort的操作）、hash（可以用到hash的操作）的内存。这里就存在multiple sort/hash的问题，一个sql有多个sort的话可使用多个work_mem，所以pg13新增&lt;code&gt;hash_mem_multiplier&lt;/code&gt;以限制一个语句中的hash使用次数。但是sort呢？sort目前没有multiplier参数，但是现实场景中问题较少，因为一个语句中大量的plan node存在sort操作的情况是比较少的，想想代价就很高，优化器源码中也有把排序操作放在执行计划最后的逻辑，以减少反复排序。&lt;/p&gt;
&lt;p&gt;这里实例的work_mem为128M，并且这个库是pg13+的，hash_mem_multiplier为1，基本可以排除执行计划使用大量hash操作导致内存暴涨的问题。另外从上面的执行计划看，完全没有sort和hash操作，所以可以排除sort/hash操作过多导致的问题。&lt;/p&gt;
&lt;p&gt;所以之前的提问，&lt;em&gt;“work_mem明明不大，为什么没有起到限制operation内存的效果？”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;因为sql语句只有union all，没有任何排序和hash操作，所以work_mem不会限制这里的内存&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;其他plan node&lt;/strong&gt;:
无论怎样，work_mem只（？）限制sort/hash。plan operation有这么多类型的操作，是不是没有限制？&lt;/p&gt;

&lt;h3 class="relative group"&gt;复现问题并深入分析
 &lt;div id="复现问题并深入分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%a4%8d%e7%8e%b0%e9%97%ae%e9%a2%98%e5%b9%b6%e6%b7%b1%e5%85%a5%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;

&lt;h4 class="relative group"&gt;空表复现内存飙升
 &lt;div id="空表复现内存飙升" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%a9%ba%e8%a1%a8%e5%a4%8d%e7%8e%b0%e5%86%85%e5%ad%98%e9%a3%99%e5%8d%87" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--建空表
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; lzl1(col1 varchar(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--非常多union all的查询
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; col1 &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzl1 &lt;span style="color:#66d9ef"&gt;union&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;all&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; col1 &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzl1 &lt;span style="color:#66d9ef"&gt;union&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;all&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...(&lt;span style="color:#ae81ff"&gt;5000&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;个&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;union&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;all&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;，&lt;/span&gt;sql大小150KB)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; col1 &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzl1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;（UNION ALL过多可能超过max_stack_depth限制）
一个空表，多个union all，直接就容复现出来内存飙升问题。不仅如此，还可以发现sql运行完后，backend的内存回收了。&lt;/p&gt;
&lt;p&gt;因为是一个空表，数据文件0kb，所以可以排除数据问题导致内存飙高。所以“数据本身跟内存有关系吗？是因为返回数据过多导致的吗？”——跟数据本身关系不大。&lt;/p&gt;

&lt;h4 class="relative group"&gt;strace操作系统调用分析
 &lt;div id="strace操作系统调用分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#strace%e6%93%8d%e4%bd%9c%e7%b3%bb%e7%bb%9f%e8%b0%83%e7%94%a8%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;执行语句的同时通过strace -p抓操作系统调用信息：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; strace -p &lt;span style="color:#ae81ff"&gt;198337&lt;/span&gt; &amp;gt; strace.198337 2&amp;gt;&amp;amp;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;在看strace信息前先了解一点点linux调用函数：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://man7.org/linux/man-pages/man2/epoll_wait.2.html" target="_blank" rel="noreferrer"&gt;epoll_wait&lt;/a&gt;:等待event，什么都不做的进程就是这个状态&lt;/li&gt;
&lt;li&gt;&lt;a href="https://man7.org/linux/man-pages/man3/recvfrom.3p.html" target="_blank" rel="noreferrer"&gt;recvfrom&lt;/a&gt;:receive a message from a socket，从socket接收消息&lt;/li&gt;
&lt;li&gt;&lt;a href="https://man7.org/linux/man-pages/man3/recvfrom.3p.html" target="_blank" rel="noreferrer"&gt;getrusage&lt;/a&gt;:get resource usage，获取资源使用情况&lt;/li&gt;
&lt;li&gt;&lt;a href="https://man7.org/linux/man-pages/man2/brk.2.html" target="_blank" rel="noreferrer"&gt;brk&lt;/a&gt;: program break.Increasing the program break has the effect of allocating memory to the process; decreasing the break deallocates memory.操作系统底层管理内存的函数，malloc本质上也是在调用brk。&lt;/li&gt;
&lt;li&gt;&lt;a href="https://man7.org/linux/man-pages/man2/lseek.2.html" target="_blank" rel="noreferrer"&gt;lseek&lt;/a&gt;:repositions the file offset of the open file description associated with the file descriptor fd to the argument offset，定位文件偏移量用的&lt;/li&gt;
&lt;li&gt;&lt;a href="" &gt;write&lt;/a&gt;:write to a file descriptor，write不保证写入磁盘&lt;/li&gt;
&lt;li&gt;&lt;a href="https://man7.org/linux/man-pages/man3/sendto.3p.html" target="_blank" rel="noreferrer"&gt;sendto&lt;/a&gt;:send a message on a socket，从socket发送消息&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;其中，lseek、write、sendto等系统函数中包含fd文件描述符信息&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lseek&lt;span style="color:#f92672"&gt;(&lt;/span&gt;37, 0, SEEK_END&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;在/proc/[pid]/pd目录中缓存了进程持有的文件描述符，从文件描述符反查relation，可以找到SQL执行打开的表lzl1&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;postgres@lzl&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ cd /proc/198337/fd
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;postgres@lzl&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ ll &lt;span style="color:#ae81ff"&gt;37&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lrwx------ &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres &lt;span style="color:#ae81ff"&gt;64&lt;/span&gt; Jan &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt; 22:59 &lt;span style="color:#ae81ff"&gt;37&lt;/span&gt; -&amp;gt; /pgdata/lzl/data13/base/16385/16386
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;postgres@lzl&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ oid2name -d lzldb -f &lt;span style="color:#ae81ff"&gt;16386&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;From database &lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filenode Table Name
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;16386&lt;/span&gt; lzl1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;strace信息非常多，但是结构简单：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;strace: Process &lt;span style="color:#ae81ff"&gt;198337&lt;/span&gt; attached
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;epoll_wait&lt;span style="color:#f92672"&gt;(&lt;/span&gt;4, &lt;span style="color:#f92672"&gt;[{&lt;/span&gt;EPOLLIN, &lt;span style="color:#f92672"&gt;{&lt;/span&gt;u32&lt;span style="color:#f92672"&gt;=&lt;/span&gt;44314568, u64&lt;span style="color:#f92672"&gt;=&lt;/span&gt;44314568&lt;span style="color:#f92672"&gt;}}]&lt;/span&gt;, 1, -1&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## step1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;recvfrom&lt;span style="color:#f92672"&gt;(&lt;/span&gt;9, &lt;span style="color:#e6db74"&gt;&amp;#34;Q\0\2p\372select col1 from lzl1 union&amp;#34;&lt;/span&gt;..., 8192, 0, NULL, NULL&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8192&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;recvfrom&lt;span style="color:#f92672"&gt;(&lt;/span&gt;9, &lt;span style="color:#e6db74"&gt;&amp;#34; all\nselect col1 from lzl1 union&amp;#34;&lt;/span&gt;..., 8192, 0, NULL, NULL&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8192&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;recvfrom&lt;span style="color:#f92672"&gt;(&lt;/span&gt;9, &lt;span style="color:#e6db74"&gt;&amp;#34; all\nselect col1 from lzl1 union&amp;#34;&lt;/span&gt;..., 8192, 0, NULL, NULL&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8192&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;recvfrom&lt;span style="color:#f92672"&gt;(&lt;/span&gt;9, &lt;span style="color:#e6db74"&gt;&amp;#34; all\nselect col1 from lzl1 union&amp;#34;&lt;/span&gt;..., 8192, 0, NULL, NULL&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8192&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;recvfrom&lt;span style="color:#f92672"&gt;(&lt;/span&gt;9, &lt;span style="color:#e6db74"&gt;&amp;#34; all\nselect col1 from lzl1 union&amp;#34;&lt;/span&gt;..., 8192, 0, NULL, NULL&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4347&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## step2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;NULL&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x34d5000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;0x3cd5000&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x3cd5000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;NULL&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x3cd5000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;NULL&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x88cd6000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;0x894d6000&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x894d6000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## step3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lseek&lt;span style="color:#f92672"&gt;(&lt;/span&gt;37, 0, SEEK_END&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lseek&lt;span style="color:#f92672"&gt;(&lt;/span&gt;37, 0, SEEK_END&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lseek&lt;span style="color:#f92672"&gt;(&lt;/span&gt;37, 0, SEEK_END&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## step4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;NULL&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x89cd6000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;0x8a4d6000&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x8a4d6000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;NULL&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x8a4d6000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;NULL&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x8a516000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;0x8a556000&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x8a556000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## step5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;write&lt;span style="color:#f92672"&gt;(&lt;/span&gt;2, &lt;span style="color:#e6db74"&gt;&amp;#34;2024-01-26 23:08:01.800 CST [198&amp;#34;&lt;/span&gt;..., 165521&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;165521&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;NULL&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x8a556000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;0x8a57d000&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x8a57d000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;NULL&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x8a57d000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;0x8a59f000&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x8a59f000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;NULL&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x8d449000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;0x8d46b000&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x8d46b000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;NULL&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x8d46b000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;0x8d48d000&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x8d48d000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#step6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lseek&lt;span style="color:#f92672"&gt;(&lt;/span&gt;37, 0, SEEK_END&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lseek&lt;span style="color:#f92672"&gt;(&lt;/span&gt;37, 0, SEEK_END&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lseek&lt;span style="color:#f92672"&gt;(&lt;/span&gt;37, 0, SEEK_END&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#step7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;NULL&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x8dcb1000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;NULL&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x8dcb1000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;0x8c179000&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x8c179000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;NULL&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x8c179000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;NULL&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x8c179000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;NULL&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x8c179000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;0x8a526000&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x8a526000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;0x34d5000&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x34d5000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brk&lt;span style="color:#f92672"&gt;(&lt;/span&gt;NULL&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0x34d5000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#step8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sendto&lt;span style="color:#f92672"&gt;(&lt;/span&gt;8, &lt;span style="color:#e6db74"&gt;&amp;#34;\2\0\0\0\230\0\0\0\1@\0\0\1\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&amp;#34;&lt;/span&gt;..., 152, 0, NULL, 0&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;152&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sendto&lt;span style="color:#f92672"&gt;(&lt;/span&gt;9, &lt;span style="color:#e6db74"&gt;&amp;#34;T\0\0\0\35\0\1col1\0\0\0\0\0\0\0\0\0\4\23\377\377\0\0\0\5\0\0C\0&amp;#34;&lt;/span&gt;..., 50, 0, NULL, 0&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;50&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#step9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;recvfrom&lt;span style="color:#f92672"&gt;(&lt;/span&gt;9, 0xddcf60, 8192, 0, NULL, NULL&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; -1 EAGAIN &lt;span style="color:#f92672"&gt;(&lt;/span&gt;Resource temporarily unavailable&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;epoll_wait&lt;span style="color:#f92672"&gt;(&lt;/span&gt;4, strace: Process &lt;span style="color:#ae81ff"&gt;198337&lt;/span&gt; detached
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;detached ...&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;从fd=9的socket接收到message，也就是我们发送的union all语句&lt;/li&gt;
&lt;li&gt;brk分配内存，进程的内存从0x34d5000（54MB）涨到0x894d6000（2.1GB）&lt;/li&gt;
&lt;li&gt;lseek表lzl1&lt;/li&gt;
&lt;li&gt;内存上涨4MB&lt;/li&gt;
&lt;li&gt;write到fd=2的文件，就是日志文件；内存上涨48MB&lt;/li&gt;
&lt;li&gt;lseek表lzl1&lt;/li&gt;
&lt;li&gt;内存到达峰值0x8dcb1000（2.1GB），开始通过brk释放内存，直到0x34d5000（54MB），跟开始时分毫不差&lt;/li&gt;
&lt;li&gt;从socket返回消息，也就是返回查询结果&lt;/li&gt;
&lt;li&gt;从fd=9的socket接收到空消息&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;strace分析到的东西不多，不过可以看到操作系统为进程分配和释放内存的具体过程。&lt;/p&gt;

&lt;h4 class="relative group"&gt;dump内存分析
 &lt;div id="dump内存分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#dump%e5%86%85%e5%ad%98%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;内存飙高后的pmap信息：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;postgres@lzl pg_log&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ pmap -x &lt;span style="color:#ae81ff"&gt;76207&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;76207: postgres: postgres lzldb &lt;span style="color:#f92672"&gt;[&lt;/span&gt;local&lt;span style="color:#f92672"&gt;]&lt;/span&gt; SELECT 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Address Kbytes RSS Dirty Mode Mapping
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;0000000000400000&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7984&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2192&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; r-x-- postgres
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;0000000000dcc000 &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; r---- postgres
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;0000000000dcd000 &lt;span style="color:#ae81ff"&gt;60&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;60&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;60&lt;/span&gt; rw--- postgres
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;0000000000ddc000 &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;60&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;60&lt;/span&gt; rw--- &lt;span style="color:#f92672"&gt;[&lt;/span&gt; anon &lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;0000000001e49000 &lt;span style="color:#ae81ff"&gt;264&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;224&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;224&lt;/span&gt; rw--- &lt;span style="color:#f92672"&gt;[&lt;/span&gt; anon &lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;0000000001e8b000 &lt;span style="color:#ae81ff"&gt;1812380&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1804400&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1804400&lt;/span&gt; rw--- &lt;span style="color:#f92672"&gt;[&lt;/span&gt; anon &lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ffffffffff600000 &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; r-x-- &lt;span style="color:#f92672"&gt;[&lt;/span&gt; anon &lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---------------- ------- ------- ------- 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;total kB &lt;span style="color:#ae81ff"&gt;2089384&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1810232&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1807384&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;pmap这里没有展示具体段是什么，但是可以确认内存起始地址为1e49000的内存段占用最多。此时需要smap来看是什么段，smap的段信息更为准确：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;postgres@lzl 76207&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ cat smaps |grep 1e49000 -A &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;01e49000-01e8b000 rw-p &lt;span style="color:#ae81ff"&gt;00000000&lt;/span&gt; 00:00 &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;heap&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Size: &lt;span style="color:#ae81ff"&gt;264&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;01e8b000-70872000 rw-p &lt;span style="color:#ae81ff"&gt;00000000&lt;/span&gt; 00:00 &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;heap&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Size: &lt;span style="color:#ae81ff"&gt;1812380&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Rss: &lt;span style="color:#ae81ff"&gt;1804400&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Pss: &lt;span style="color:#ae81ff"&gt;1804400&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Shared_Clean: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Shared_Dirty: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Private_Clean: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Private_Dirty: &lt;span style="color:#ae81ff"&gt;1804400&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Referenced: &lt;span style="color:#ae81ff"&gt;1804400&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Anonymous: &lt;span style="color:#ae81ff"&gt;1804400&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;AnonHugePages: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Swap: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;KernelPageSize: &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;MMUPageSize: &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; kB&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;heap段，PSS进程私有内存达到1.8GB！
&lt;em&gt;（这里本来应该dump 01e8b000-70872000内存段，但是gdb dump memory会报错，不太明白具体原因，大佬可以指点一下，谢谢！）&lt;/em&gt;
这里粗糙一点用gcore dump内存，比较难看，什么东西都有，没有发现占用特别多的内容。不过strings后发现内存数据实际上很少：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;postgres@lzl lzl&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ gcore -o /pgdata/lzl/gcore.dump &lt;span style="color:#ae81ff"&gt;76207&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;postgres@lzl lzl&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ strings gcore.dump.76207&amp;gt; text.dump.76207
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;postgres@lzl lzl&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ ll -h
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw-r----- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres 2.0G Jan &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt; 17:29 gcore.dump.76207
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw-r----- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; postgres postgres 5.2M Jan &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt; 17:30 text.dump.76207&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;申请了2G的虚拟内存，占用1.8G的物理内存，实际上只存储了5.2M的数据！
用hexdump极粗略地看一下，可以发现很多内存空洞&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;postgres@lzl lzl&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ hexdump -C gcore.dump.76207 |head -10000 |grep &lt;span style="color:#e6db74"&gt;&amp;#34;00 00 00 00 00 00 00 00&amp;#34;&lt;/span&gt;|wc -l
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;3690&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 class="relative group"&gt;log_planner_stats等信息
 &lt;div id="log_planner_stats等信息" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#log_planner_stats%e7%ad%89%e4%bf%a1%e6%81%af" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;为了验证是否缓存执行计划的问题
把复现环境的相关log参数&lt;strong&gt;先后&lt;/strong&gt;打开以观察parse、planner、executor阶段的资源消耗&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; log_parser_stats &lt;span style="color:#f92672"&gt;=&lt;/span&gt; on
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; log_planner_stats &lt;span style="color:#f92672"&gt;=&lt;/span&gt; on
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; log_executor_stats &lt;span style="color:#f92672"&gt;=&lt;/span&gt; on&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;从日志上看parse阶段的消耗内存较少，而planner的内存消耗较多
log planner stat的信息：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-01-26 18:01:41.592 CST &lt;span style="color:#f92672"&gt;[&lt;/span&gt;208503&lt;span style="color:#f92672"&gt;]&lt;/span&gt; LOG: PLANNER STATISTICS
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-01-26 18:01:41.592 CST &lt;span style="color:#f92672"&gt;[&lt;/span&gt;208503&lt;span style="color:#f92672"&gt;]&lt;/span&gt; DETAIL: ! system usage stats:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ! 0.048955 s user, 0.004996 s system, 0.054077 s elapsed
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ! &lt;span style="color:#f92672"&gt;[&lt;/span&gt;11.208034 s user, 1.313838 s system total&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ! &lt;span style="color:#ae81ff"&gt;2255352&lt;/span&gt; kB max resident size
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ! 0/0 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0/352&lt;span style="color:#f92672"&gt;]&lt;/span&gt; filesystem blocks in/out
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ! 0/1315 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0/563859&lt;span style="color:#f92672"&gt;]&lt;/span&gt; page faults/reclaims, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0&lt;span style="color:#f92672"&gt;]&lt;/span&gt; swaps
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ! &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0&lt;span style="color:#f92672"&gt;]&lt;/span&gt; signals rcvd, 0/0 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0/0&lt;span style="color:#f92672"&gt;]&lt;/span&gt; messages rcvd/sent
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ! 0/0 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;1/16&lt;span style="color:#f92672"&gt;]&lt;/span&gt; voluntary/involuntary context switches&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;2GB的max resident size大小跟进程观察的res差不多，所以上面的信息可以回答刚才的问题：“是解析数据缓存大，还是因为执行计划缓存数据大？”——planner阶段消耗的内存。&lt;/p&gt;

&lt;h4 class="relative group"&gt;查看TopMemoryContext
 &lt;div id="查看topmemorycontext" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%9f%a5%e7%9c%8btopmemorycontext" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;pg通过memorycontext管理backend进程的私有内存，可通过gdb输出TopMemoryContext信息：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;TopMemoryContext: &lt;span style="color:#ae81ff"&gt;101488&lt;/span&gt; total in &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; blocks; &lt;span style="color:#ae81ff"&gt;48464&lt;/span&gt; free &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;28&lt;/span&gt; chunks&lt;span style="color:#f92672"&gt;)&lt;/span&gt;; &lt;span style="color:#ae81ff"&gt;53024&lt;/span&gt; used
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pgstat TabStatusArray lookup hash table: &lt;span style="color:#ae81ff"&gt;8192&lt;/span&gt; total in &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; blocks; &lt;span style="color:#ae81ff"&gt;1408&lt;/span&gt; free &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; chunks&lt;span style="color:#f92672"&gt;)&lt;/span&gt;; &lt;span style="color:#ae81ff"&gt;6784&lt;/span&gt; used
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; TopTransactionContext: &lt;span style="color:#ae81ff"&gt;8192&lt;/span&gt; total in &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; blocks; &lt;span style="color:#ae81ff"&gt;7720&lt;/span&gt; free &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; chunks&lt;span style="color:#f92672"&gt;)&lt;/span&gt;; &lt;span style="color:#ae81ff"&gt;472&lt;/span&gt; used
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; TableSpace cache: &lt;span style="color:#ae81ff"&gt;8192&lt;/span&gt; total in &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; blocks; &lt;span style="color:#ae81ff"&gt;2048&lt;/span&gt; free &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; chunks&lt;span style="color:#f92672"&gt;)&lt;/span&gt;; &lt;span style="color:#ae81ff"&gt;6144&lt;/span&gt; used
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; RowDescriptionContext: &lt;span style="color:#ae81ff"&gt;8192&lt;/span&gt; total in &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; blocks; &lt;span style="color:#ae81ff"&gt;6880&lt;/span&gt; free &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; chunks&lt;span style="color:#f92672"&gt;)&lt;/span&gt;; &lt;span style="color:#ae81ff"&gt;1312&lt;/span&gt; used
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MessageContext: &lt;span style="color:#ae81ff"&gt;1854981336&lt;/span&gt; total in &lt;span style="color:#ae81ff"&gt;235&lt;/span&gt; blocks; &lt;span style="color:#ae81ff"&gt;7911304&lt;/span&gt; free &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt; chunks&lt;span style="color:#f92672"&gt;)&lt;/span&gt;; &lt;span style="color:#ae81ff"&gt;1847070032&lt;/span&gt; used
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Grand total: &lt;span style="color:#ae81ff"&gt;1856104056&lt;/span&gt; bytes in &lt;span style="color:#ae81ff"&gt;431&lt;/span&gt; blocks; &lt;span style="color:#ae81ff"&gt;8226712&lt;/span&gt; free &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;179&lt;/span&gt; chunks&lt;span style="color:#f92672"&gt;)&lt;/span&gt;; &lt;span style="color:#ae81ff"&gt;1847877344&lt;/span&gt; used&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;内存消耗最多的是MessageContext 1.8G
src/backend/utils/mmgr/README对MessageContext 的解释：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;MessageContext &amp;mdash; this context holds the current command message from the frontend, as well as any derived storage that need only live as long as the current message (for example, in simple-Query mode the parse and plan trees can live here). This context will be reset, and any children deleted, at the top of each cycle of the outer loop of PostgresMain. This is kept separate from per-transaction and per-portal contexts because a query string might need to live either a longer or shorter time than any single transaction or portal.&lt;/p&gt;
&lt;/blockquote&gt;&lt;blockquote&gt;&lt;p&gt;When creating a prepared statement, the parse and plan trees will be built in a temporary context that&amp;rsquo;s a child of MessageContext&lt;/p&gt;
&lt;/blockquote&gt;&lt;ul&gt;
&lt;li&gt;MessageContext缓存frontend发来传递的消息，包含派生的parse、plan tree信息&lt;/li&gt;
&lt;li&gt;parse and plan trees 是MessageContext的child，也就是说MessageContext回收，parse and plan trees 就回收&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这里就的messagecontext还可以解释私有内存回收问题，planner阶段产生的plan tree内存数据是MessageContext的child，数据结果返回后MessageContext被回收，child内容也被回收，同样也可以解释从strace中观察的内存释放后跟释放前的大小是完全一致的。&lt;/p&gt;

&lt;h3 class="relative group"&gt;总结
 &lt;div id="总结" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%80%bb%e7%bb%93" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;回答最后一个问题：&lt;em&gt;“为什么5M的SQL可以把内存打到70GB？”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;绝大部分内存是在生产执行计划期间消耗的，planner申请了大量的内存，并且work_mem，hash_mem_multiplier只能限制到排序操作和hash操作，对于planner过程中的其他内存操作还无法限制，planner本身产生的plan tree并不大，但是申请内存时存在大量的内存空洞，导致本身M级的数据（元数据、parse tree、plan tree等等）存储在G级的内存中。&lt;/p&gt;
&lt;p&gt;这些SQL、parse tree、plan tree都缓存在MessageContext及其child中，消息发送完毕后，此部分产生的内存全部回收。&lt;/p&gt;</content:encoded></item><item><title>较少的分区也报错too many range table entries</title><link>https://lastdba.com/2024/08/12/%E8%BE%83%E5%B0%91%E7%9A%84%E5%88%86%E5%8C%BA%E4%B9%9F%E6%8A%A5%E9%94%99too-many-range-table-entries/</link><pubDate>Mon, 12 Aug 2024 00:00:00 +0000</pubDate><guid>https://lastdba.com/2024/08/12/%E8%BE%83%E5%B0%91%E7%9A%84%E5%88%86%E5%8C%BA%E4%B9%9F%E6%8A%A5%E9%94%99too-many-range-table-entries/</guid><description>&lt;h2 class="relative group"&gt;问题现象
 &lt;div id="问题现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;postgresql中update执行语句报错&lt;code&gt;too many range table entries&lt;/code&gt;
源sql&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; t &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; LZLTAB &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8723&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;limit&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;update&lt;/span&gt;	LZLTAB &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	STATUS &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;00&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	FILE_ID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	DATE_UPDATED &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;localtimestamp&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt;	id &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; t)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;如果把update改写成select，可以执行成功&lt;/p&gt;</description><content:encoded>
&lt;h2 class="relative group"&gt;问题现象
 &lt;div id="问题现象" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e7%8e%b0%e8%b1%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;postgresql中update执行语句报错&lt;code&gt;too many range table entries&lt;/code&gt;
源sql&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; t &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; LZLTAB &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8723&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;limit&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;update&lt;/span&gt;	LZLTAB &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	STATUS &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;00&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	FILE_ID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	DATE_UPDATED &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;localtimestamp&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt;	id &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; t)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;如果把update改写成select，可以执行成功&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; t &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt;	id &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt;	LZLTAB &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt;	id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8723&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;limit&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; 	LZLTAB &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt;	id &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; id	&lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; t)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; id &lt;span style="color:#f92672"&gt;|&lt;/span&gt; date_created 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;------+----------------------------+...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;8723&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2023&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;06&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;161687&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;row&lt;/span&gt;)	&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;主键和分区是这样，分区总共有400个&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Partition &lt;span style="color:#66d9ef"&gt;key&lt;/span&gt;: RANGE (partition_key)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Indexes:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;pk_lzl&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;KEY&lt;/span&gt;, btree (id, partition_key)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Partitions: lzl_p20230601 &lt;span style="color:#66d9ef"&gt;FOR&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;VALUES&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;20230601&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;TO&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;20230602&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; lzl_p20230602 &lt;span style="color:#66d9ef"&gt;FOR&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;VALUES&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;20230602&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;TO&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;20230603&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; lzl_p20230603 &lt;span style="color:#66d9ef"&gt;FOR&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;VALUES&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;20230603&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;TO&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;20230604&amp;#39;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;sql逻辑有很多优化点，但是这里不讨论优化。重点是分析为什么update会报错，和为什么select和update会有区别。
执行explain update报错如下：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; t &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; (selec tid &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; LZLTAB &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8723&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;limit&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;update&lt;/span&gt; LZLTAB &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;STATUS &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;00&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;FILE_ID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;DATE_UPDATED &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;localtimestamp&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; t);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ERROR: &lt;span style="color:#ae81ff"&gt;54000&lt;/span&gt;: too many range &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; entries
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;LOCATION&lt;/span&gt;: add_rte_to_flat_rtable, setrefs.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;451&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Time: &lt;span style="color:#ae81ff"&gt;18341&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;171&lt;/span&gt; ms (&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;341&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;explain卡了18秒，然后报错&lt;/p&gt;

&lt;h2 class="relative group"&gt;源码分析
 &lt;div id="源码分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%ba%90%e7%a0%81%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;报错直接抛出了源码的位置&lt;code&gt;LOCATION: add_rte_to_flat_rtable, setrefs.c:451 &lt;/code&gt;，直接找到该源码&lt;/p&gt;
&lt;p&gt;&lt;code&gt;src/backend/optimizer/plan/setrefs.c&lt;/code&gt;
其注释是说setrefs.c是完成计划树后的相关工作的&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *Post-processing of a completed plan tree: fix references to subplan
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *	 vars, compute regproc values for operators, etc
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;找到第451行的函数：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Add (a copy of) the given RTE to the final rangetable
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * In the flat rangetable, we zero out substructure pointers that are not
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * needed by the executor; this reduces the storage space and copying cost
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * for cached plans. We keep only the ctename, alias and eref Alias fields,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * which are needed by EXPLAIN, and the selectedCols, insertedCols,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * updatedCols, and extraUpdatedCols bitmaps, which are needed for
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * executor-startup permissions checking and for trigger event checking.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;add_rte_to_flat_rtable&lt;/span&gt;(PlannerGlobal &lt;span style="color:#f92672"&gt;*&lt;/span&gt;glob, RangeTblEntry &lt;span style="color:#f92672"&gt;*&lt;/span&gt;rte)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * Check for RT index overflow; it&amp;#39;s very unlikely, but if it did happen,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * the executor would get confused by varnos that match the special varno
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 * values.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;	 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;IS_SPECIAL_VARNO&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;list_length&lt;/span&gt;(glob&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;finalrtable)))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;ereport&lt;/span&gt;(ERROR,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				(&lt;span style="color:#a6e22e"&gt;errcode&lt;/span&gt;(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				 &lt;span style="color:#a6e22e"&gt;errmsg&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;too many range table entries&amp;#34;&lt;/span&gt;)));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;errmsg()就是第451行。add_rte_to_flat_rtable()看注释跟RTE有关，什么RTE呢？下面再分析。
报错的判断是&lt;code&gt;IS_SPECIAL_VARNO()&lt;/code&gt;，直接搜索该函数，在&lt;code&gt;src/include/nodes/primnodes.h&lt;/code&gt;中找到宏定义&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Var - expression node representing a variable (ie, a table column)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * In the parser and planner, varno and varattno identify the semantic
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * referent, which is a base-relation column unless the reference is to a join
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * USING column that isn&amp;#39;t semantically equivalent to either join input column
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * (because it is a FULL join or the input column requires a type coercion).
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * In those cases varno and varattno refer to the JOIN RTE. (Early in the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * planner, we replace such join references by the implied expression; but up
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * till then we want join reference Vars to keep their original identity for
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * query-printing purposes.)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define INNER_VAR		65000	&lt;/span&gt;&lt;span style="color:#75715e"&gt;/* reference to inner subplan */&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define OUTER_VAR		65001	&lt;/span&gt;&lt;span style="color:#75715e"&gt;/* reference to outer subplan */&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define INDEX_VAR		65002	&lt;/span&gt;&lt;span style="color:#75715e"&gt;/* reference to index column */&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define IS_SPECIAL_VARNO(varno)		((varno) &amp;gt;= INNER_VAR)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;上面一段注释有点难懂，但是有段话很重要：&lt;em&gt;In those cases varno and varattno refer to the JOIN RTE&lt;/em&gt;。varno与RTE有关系。
然后&lt;code&gt;varno&amp;gt;=65000&lt;/code&gt;时，会抛出报错。（这里不扩展&lt;code&gt;INNER_VAR&lt;/code&gt;,&lt;code&gt;OUTER_VAR&lt;/code&gt;,&lt;code&gt;INDEX_VAR&lt;/code&gt;的区别，因为他们的值差别不大，不影响我们继续分析）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;什么是RTE？&lt;/strong&gt;
在执行计划源码中的各个位置都能找到RTE（rangetable或RangeTblEntry）的描述，并且报错也很明显&lt;code&gt;ERROR: 54000: too many range table entries&lt;/code&gt;也是说的RTE。那么什么是RTE？
在&lt;code&gt;src/include/nodes/parsenodes.h&lt;/code&gt;中有一段对RTE的描述&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*--------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * RangeTblEntry -
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *	 A range table is a List of RangeTblEntry nodes.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *	 A range table entry may represent a plain relation, a sub-select in
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *	 FROM, or the result of a JOIN clause. (Only explicit JOIN syntax
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *	 produces an RTE, not the implicit join resulting from multiple FROM
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *	 items. This is because we only need the RTE to deal with SQL features
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *	 like outer joins and join-output-column aliasing.) Other special
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *	 RTE types also exist, as indicated by RTEKind.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *	 Note that we consider RTE_RELATION to cover anything that has a pg_class
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; *	 entry. relkind distinguishes the sub-cases.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; */&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;简单的说，RTE是执行计划中的“表”，可以是具体的表也可以是生成类的“表”，比如子查询、join结果等等。RTE超出限制65000，也就是说执行计划中生成了太多的RTE。&lt;/p&gt;

&lt;h2 class="relative group"&gt;查看update的执行计划
 &lt;div id="查看update的执行计划" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%9f%a5%e7%9c%8bupdate%e7%9a%84%e6%89%a7%e8%a1%8c%e8%ae%a1%e5%88%92" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;由于我们知道了RTE的啥，所以查看sql的执行计划可能会有所帮助。但是由于源sql（400个分区）没有生成执行计划，我们创建一个30个分区的表，期待它能explain出来，然后观察它的执行计划。
30个分区的表执行相同的update语句&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; t &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzl &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8723&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;limit&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;update&lt;/span&gt; lzl &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;STATUS &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;00&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;FILE_ID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;DATE_UPDATED &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;localtimestamp&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; ( &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; t);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;生成的执行计划如下&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-----------------------------------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Update&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;155&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;48&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;4980&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;600&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3042&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Update&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_p20230601 lzl_1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Update&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_p20230602 lzl_2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Update&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_p20230630 lzl_30
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Hash Semi &lt;span style="color:#66d9ef"&gt;Join&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;155&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;48&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;166&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3042&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Hash Cond: (lzl_1.id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; t.id)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Seq Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_p20230601 lzl_1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2912&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Hash (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;155&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;155&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;40&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Subquery Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; t (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;155&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;40&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Limit&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;154&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;80&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Append (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;154&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;80&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Only&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; lzl_p20230601_pkey &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_p20230601 lzl_32 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8723&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Only&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; lzl_p20230602_pkey &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_p20230602 lzl_33 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8723&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Only&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; lzl_p20230630_pkey &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_p20230630 lzl_61 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8723&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Hash Semi &lt;span style="color:#66d9ef"&gt;Join&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;155&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;48&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;166&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3042&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Hash Cond: (lzl_30.id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; t_29.id)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Seq Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_p20230630 lzl_30 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2912&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Hash (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;155&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;155&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;40&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Subquery Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; t_29 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;155&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;40&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Limit&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;154&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;80&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Append (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;154&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;80&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Only&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; lzl_p20230601_pkey &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_p20230601 lzl_931 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8723&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Only&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; lzl_p20230602_pkey &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_p20230602 lzl_932 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8723&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;								...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Only&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; lzl_p20230630_pkey &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_p20230630 lzl_960 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8723&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;2041&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;执行计划非常长，总共有2041行。这个执行计划非常笨，每个分区在更新的时候，都把谓词条件在分区表中运行了一次，由于sql没有分区键，每次运行又扫描了所有分区。本身30个分区的分区表，每个分区扫描了30次，总共扫描900次分区。
从执行计划也能看到RTE表刚开始有30个，分配给update直到lzl_30；后面每次hash匹配时每个分区扫描也分配了30个RTE，比如lzl_1对应的hash下的分区扫描从lzl_32到lzl_61。这里为什么是32而不是31？因为整个分区扫描是一个子查询也是一个RTE，为t(所有的为t,t1-t_29)，也是总共30个。所以执行计划中生成的RTE表总共有30+30+30*30=960个。&lt;/p&gt;
&lt;p&gt;如果用select来看执行计划，发现跟update的执行计划有很大的不同&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; t &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzl &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8723&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;limit&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; STATUS ,FILE_ID ,DATE_UPDATED &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzl &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; ( &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; t);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Hash Semi &lt;span style="color:#66d9ef"&gt;Join&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;155&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;48&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;467&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;90&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;98&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Hash Cond: (lzl.id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; lzl_31.id)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Append (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;309&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;600&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;106&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Seq Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_p20230601 lzl_1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;106&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Seq Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_p20230602 lzl_2 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;106&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Seq Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_p20230630 lzl_30 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;106&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Hash (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;155&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;155&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Limit&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;154&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;80&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Append (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;154&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;80&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Only&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; lzl_p20230601_pkey &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_p20230601 lzl_32 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8723&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Only&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; lzl_p20230602_pkey &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_p20230602 lzl_33 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8723&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Only&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; lzl_p20230630_pkey &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl_p20230630 lzl_61 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8723&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;96&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;没有反复（笛卡尔集式地）访问表，RTE只到了61个。这也是为什么400个分区的select可以查询出来的原因，因为400*400次访问实在太多了。
所以关于之前的sql，update执行报错，而select正常的情况，可以得出结论：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;400个分区的select，它的执行计划中的RTE有801个，没超过&lt;code&gt;INNER_VAR&lt;/code&gt;的值65000，它可以生成执行计划并且执行&lt;/li&gt;
&lt;li&gt;400个分区的update，它的执行计划中的RTE有160160400个，远远超过&lt;code&gt;INNER_VAR&lt;/code&gt;的值65000，不能成功生成执行计划，抛出RTE超限的报错。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;原因分析的差不多了，但是select和update的执行计划差别很大，仍然感到疑惑。下面横向对比oracle和mysql的执行计划，看看有什么差别。&lt;/p&gt;

&lt;h3 class="relative group"&gt;ORACLE的行为
 &lt;div id="oracle的行为" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#oracle%e7%9a%84%e8%a1%8c%e4%b8%ba" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;oracle库创建分区表，并使用本地索引&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;CREATE&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;TABLE&lt;/span&gt; lzl (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; id number &lt;span style="color:#66d9ef"&gt;NOT&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; partition_key number &lt;span style="color:#66d9ef"&gt;DEFAULT&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NOT&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PARTITION &lt;span style="color:#66d9ef"&gt;BY&lt;/span&gt; RANGE (partition_key)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PARTITION lzl_p20230601 &lt;span style="color:#66d9ef"&gt;VALUES&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;LESS&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;THAN&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;20230602&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PARTITION lzl_p20230602 &lt;span style="color:#66d9ef"&gt;VALUES&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;LESS&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;THAN&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;20230603&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PARTITION lzl_p20230630 &lt;span style="color:#66d9ef"&gt;VALUES&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;LESS&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;THAN&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;20230631&amp;#39;&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; PKLZL &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzl(id, partition_key) &lt;span style="color:#66d9ef"&gt;local&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;alter&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; lzl &lt;span style="color:#66d9ef"&gt;add&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;constraint&lt;/span&gt; pklzl &lt;span style="color:#66d9ef"&gt;primary&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;key&lt;/span&gt; (id, partition_key) &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; pklzl;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;执行计划：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; t &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzl &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8723&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;and&lt;/span&gt; rownum&lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; STATUS ,FILE_ID ,DATE_UPDATED &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzl &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; ( &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; t)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/e6b4077b9290.png" alt="image.png" /&gt;&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;update&lt;/span&gt; lzl &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;STATUS &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;00&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;FILE_ID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;DATE_UPDATED &lt;span style="color:#f92672"&gt;=&lt;/span&gt; sysdate
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzl &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8723&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;and&lt;/span&gt; rownum&lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/35e2fc036d9f.png" alt="image.png" /&gt;
oracle里，select和update都使用了nest loop，访问所有分区partition range all，所以oracle无论是select和update，t表为驱动表，因为是in所以结果进行了排序去重，所以oracle的执行计划不是30*30次访问，而是跟驱动表里的结果集有关，如果是n条数据，那么访问n*30次分区。因为驱动表t没有什么数据，所以这个执行计划没什么问题。&lt;/p&gt;

&lt;h3 class="relative group"&gt;mysql的行为
 &lt;div id="mysql的行为" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#mysql%e7%9a%84%e8%a1%8c%e4%b8%ba" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;因为mysql只支持本地索引，所以直接建主键就行了&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;CREATE&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;TABLE&lt;/span&gt; test (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; id bigint &lt;span style="color:#66d9ef"&gt;NOT&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; date_created &lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; ,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PARTITION &lt;span style="color:#66d9ef"&gt;BY&lt;/span&gt; RANGE (partition_key) 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PARTITION lzl_p20230601 &lt;span style="color:#66d9ef"&gt;VALUES&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;LESS&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;THAN&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;20230602&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PARTITION lzl_p20230602 &lt;span style="color:#66d9ef"&gt;VALUES&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;LESS&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;THAN&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;20230603&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PARTITION lzl_p20230630 &lt;span style="color:#66d9ef"&gt;VALUES&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;LESS&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;THAN&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;20230631&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;alter&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; lzl &lt;span style="color:#66d9ef"&gt;add&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;primary&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;key&lt;/span&gt; pklzl(id,partition_key);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;mysql从5.7开始执行计划会显示扫描了哪些分区，这里的版本是8.0的。
select的执行计划：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; t &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzl &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8723&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;limit&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; STATUS ,FILE_ID ,DATE_UPDATED &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzl &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; ( &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; t);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#75715e"&gt;----+-------------+------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------+---------------+---------+---------+-------+------+----------+-----------------+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; id &lt;span style="color:#f92672"&gt;|&lt;/span&gt; select_type &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; partitions &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; possible_keys &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;key&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; key_len &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ref&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; filtered &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Extra &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#75715e"&gt;----+-------------+------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------+---------------+---------+---------+-------+------+----------+-----------------+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;derived3&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ALL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Start&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;temporary&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzl &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzl_p20230601,lzl_p20230602,lzl_p20230603,lzl_p20230604,lzl_p20230605,lzl_p20230606,lzl_p20230607,lzl_p20230608,lzl_p20230609,lzl_p20230610,lzl_p20230611,lzl_p20230612,lzl_p20230613,lzl_p20230614,lzl_p20230615,lzl_p20230616,lzl_p20230617,lzl_p20230618,lzl_p20230619,lzl_p20230620,lzl_p20230621,lzl_p20230622,lzl_p20230623,lzl_p20230624,lzl_p20230625,lzl_p20230626,lzl_p20230627,lzl_p20230628,lzl_p20230629,lzl_p20230630 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ref&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t.id &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;End&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;temporary&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; DERIVED &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzl &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzl_p20230601,lzl_p20230602,lzl_p20230603,lzl_p20230604,lzl_p20230605,lzl_p20230606,lzl_p20230607,lzl_p20230608,lzl_p20230609,lzl_p20230610,lzl_p20230611,lzl_p20230612,lzl_p20230613,lzl_p20230614,lzl_p20230615,lzl_p20230616,lzl_p20230617,lzl_p20230618,lzl_p20230619,lzl_p20230620,lzl_p20230621,lzl_p20230622,lzl_p20230623,lzl_p20230624,lzl_p20230625,lzl_p20230626,lzl_p20230627,lzl_p20230628,lzl_p20230629,lzl_p20230630 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ref&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; const &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Using&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;update的执行计划：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; t &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzl &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8723&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;limit&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;update&lt;/span&gt; lzl &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; STATUS &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;00&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; FILE_ID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; DATE_UPDATED &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;localtimestamp&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; ( &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; id &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; t);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#75715e"&gt;----+-------------+------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------+---------------+---------+---------+-------+------+----------+-----------------+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; id &lt;span style="color:#f92672"&gt;|&lt;/span&gt; select_type &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; partitions &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; possible_keys &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;key&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; key_len &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ref&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; filtered &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Extra &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#75715e"&gt;----+-------------+------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------+---------------+---------+---------+-------+------+----------+-----------------+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;derived3&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ALL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Start&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;temporary&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;UPDATE&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzl &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzl_p20230601,lzl_p20230602,lzl_p20230603,lzl_p20230604,lzl_p20230605,lzl_p20230606,lzl_p20230607,lzl_p20230608,lzl_p20230609,lzl_p20230610,lzl_p20230611,lzl_p20230612,lzl_p20230613,lzl_p20230614,lzl_p20230615,lzl_p20230616,lzl_p20230617,lzl_p20230618,lzl_p20230619,lzl_p20230620,lzl_p20230621,lzl_p20230622,lzl_p20230623,lzl_p20230624,lzl_p20230625,lzl_p20230626,lzl_p20230627,lzl_p20230628,lzl_p20230629,lzl_p20230630 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ref&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; t.id &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;End&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;temporary&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; DERIVED &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzl &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzl_p20230601,lzl_p20230602,lzl_p20230603,lzl_p20230604,lzl_p20230605,lzl_p20230606,lzl_p20230607,lzl_p20230608,lzl_p20230609,lzl_p20230610,lzl_p20230611,lzl_p20230612,lzl_p20230613,lzl_p20230614,lzl_p20230615,lzl_p20230616,lzl_p20230617,lzl_p20230618,lzl_p20230619,lzl_p20230620,lzl_p20230621,lzl_p20230622,lzl_p20230623,lzl_p20230624,lzl_p20230625,lzl_p20230626,lzl_p20230627,lzl_p20230628,lzl_p20230629,lzl_p20230630 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ref&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; const &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Using&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;mysql的2个执行计划都一致。但是执行计划驱动表选择有问题，const的应该为驱动表扫描次数会更少。&lt;/p&gt;

&lt;h2 class="relative group"&gt;BUG?
 &lt;div id="bug" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#bug" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;bug描述
 &lt;div id="bug描述" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#bug%e6%8f%8f%e8%bf%b0" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://postgrespro.com/list/thread-id/2482006" target="_blank" rel="noreferrer"&gt;https://postgrespro.com/list/thread-id/2482006&lt;/a&gt;
通过报错很容易就能搜到这个bug。这个bug还是德哥在2020年提交的，后面是两个源码大佬对这个bug的讨论，讨论内容比较长，总结一下：pg并不支持无限制的分区表，这在真实世界中也是能理解的，如果分区过多性能可能会急速下降。但是社区还是认为需要调整这个限制，并对源码中的&lt;code&gt;INNER_VAR&lt;/code&gt;、&lt;code&gt;Var.varno&lt;/code&gt;等进行了讨论。&lt;/p&gt;

&lt;h3 class="relative group"&gt;误导性
 &lt;div id="误导性" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%af%af%e5%af%bc%e6%80%a7" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;这个bug标题有一定的误导性，&lt;em&gt;BUG #16302: too many range table entries - when count partition table(65538 childs)&lt;/em&gt;
bug看上去说分区表的分区不能超过65538个，在讨论中也有&lt;em&gt;PG can handle up to 64K relations in a query&lt;/em&gt;，一个查询不能有超过64K的relation。
这个就很奇怪，因为我这里的表是400个分区，然后就抛出报错了。实际上上面两个描述不太准确。因为64K的限制指的是执行计划中“表”，不全等于真实的表。当然如果表或者分区已经超过这个数，那么当然会有问题。但是如果没有超过64K，也可能是有问题的，就像我这里的案例一样，它只有400个分区。&lt;/p&gt;

&lt;h3 class="relative group"&gt;修复
 &lt;div id="修复" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%bf%ae%e5%a4%8d" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;bug提交的是12.2版本，我的环境是13.2版本的。
这个bug在pg15中修复，&lt;code&gt;src/include/nodes/primnodes.h&lt;/code&gt;源码跟之前不一样了&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define INNER_VAR		(-1)	&lt;/span&gt;&lt;span style="color:#75715e"&gt;/* reference to inner subplan */&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define OUTER_VAR		(-2)	&lt;/span&gt;&lt;span style="color:#75715e"&gt;/* reference to outer subplan */&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define INDEX_VAR		(-3)	&lt;/span&gt;&lt;span style="color:#75715e"&gt;/* reference to index column */&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define ROWID_VAR		(-4)	&lt;/span&gt;&lt;span style="color:#75715e"&gt;/* row identity column during planning */&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define IS_SPECIAL_VARNO(varno)		((int) (varno) &amp;lt; 0)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;跟社区讨论的一样，15中不仅把几个VAR都改成了负数，还把varno转换成了32位(40亿），之前是16位的（也就是65536）。
而在抛出报错的函数中，&lt;code&gt;src/backend/optimizer/plan/setrefs.c&lt;/code&gt;中的&lt;code&gt;add_rte_to_flat_rtable()&lt;/code&gt;函数中的报错代码已经被删除了！整个15的源码都没有&lt;code&gt;too many range table entries&lt;/code&gt;！&lt;/p&gt;

&lt;h2 class="relative group"&gt;总结
 &lt;div id="总结" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%80%bb%e7%bb%93" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;pg对于分区表的优化还有提升空间。pg对于分区表的分区，跟oracle、mysql不一样，它仍然子分区当成普通表来处理，而oracle只是把子分区当成一个段来处理，跟表是有差别的。这也导致pg在生产分区表执行计划时把每一个分区的访问方式都写了出来（在不会裁剪的情况下），分区特别多时执行计划会非常的长；而oracle只需要写&lt;code&gt;partition range all&lt;/code&gt;就行了；mysql也会打印所有分区，但是不会像pg那样把每个分区的访问当成一个子查询，从而降低了执行计划的复杂度。&lt;/li&gt;
&lt;li&gt;即使分区没有达到64K，也可能报错&lt;code&gt;too many range table entries&lt;/code&gt;。这个限制其实是执行计划RTE个数，而不是分区个数（当然分区达到这个数，RTE也到达了，就像上面说的，pg打印了所有分区的访问方式）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;too many range table entries&lt;/code&gt;报错在pg15解决&lt;/li&gt;
&lt;li&gt;如果是15以下的版本，确实不要建太多的分区！当然也可以利用分区裁剪来减少分区的访问，就像这个案例，把where逻辑中加上分区键条件就可以了。&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>没有阻塞为什么partition of创建子分区很慢？</title><link>https://lastdba.com/2024/08/12/%E6%B2%A1%E6%9C%89%E9%98%BB%E5%A1%9E%E4%B8%BA%E4%BB%80%E4%B9%88partition-of%E5%88%9B%E5%BB%BA%E5%AD%90%E5%88%86%E5%8C%BA%E5%BE%88%E6%85%A2/</link><pubDate>Mon, 12 Aug 2024 00:00:00 +0000</pubDate><guid>https://lastdba.com/2024/08/12/%E6%B2%A1%E6%9C%89%E9%98%BB%E5%A1%9E%E4%B8%BA%E4%BB%80%E4%B9%88partition-of%E5%88%9B%E5%BB%BA%E5%AD%90%E5%88%86%E5%8C%BA%E5%BE%88%E6%85%A2/</guid><description>&lt;h4 class="relative group"&gt;create table.. partition of语句慢分析
 &lt;div id="create-table-partition-of语句慢分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#create-table-partition-of%e8%af%ad%e5%8f%a5%e6%85%a2%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;59&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;063&lt;/span&gt; CST,&lt;span style="color:#e6db74"&gt;&amp;#34;user1&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;dblzl&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;125889&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;30.88.79.3:37423&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;66461213&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;ebc1,&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;authentication&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;59&lt;/span&gt; CST,&lt;span style="color:#ae81ff"&gt;34&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;41364668&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;,LOG,&lt;span style="color:#ae81ff"&gt;00000&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;connection authorized: user=user1 database=dblzl&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;client backend&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;59&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;079&lt;/span&gt; CST,&lt;span style="color:#e6db74"&gt;&amp;#34;user1&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;dblzl&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;125889&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;30.88.79.3:37423&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;66461213&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;ebc1,&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;59&lt;/span&gt; CST,&lt;span style="color:#ae81ff"&gt;34&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;41364669&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;,LOG,&lt;span style="color:#ae81ff"&gt;00000&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;statement: -- a86fae372f73414bbe1af18213a47beb
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;/*a86fae372f73414bbe1af18213a47beb */
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;create table if not exists table1_partition_p2406 partition of table1 for values from (&amp;#39;2024-06-01 00:00:00&amp;#39;) to (&amp;#39;2024-07-01 00:00:00&amp;#39;); &amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;client backend&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;38&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;28&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;555&lt;/span&gt; CST,&lt;span style="color:#e6db74"&gt;&amp;#34;user1&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;dblzl&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;125889&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;30.88.79.3:37423&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;66461213&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;ebc1,&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;CREATE TABLE&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;59&lt;/span&gt; CST,&lt;span style="color:#ae81ff"&gt;34&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;,LOG,&lt;span style="color:#ae81ff"&gt;00000&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;duration: 2129483.549 ms&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;client backend&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;user1这个用户在22:02:59连接进入数据库后，立即就执行了一个&lt;code&gt;create table.. partition of..&lt;/code&gt;的语句，直到22:38:28才跑完。中间的日志忽略了，一大堆会话阻塞信息，阻塞源均是125889这个会话。
被阻塞的会话类似如下：&lt;/p&gt;</description><content:encoded>
&lt;h4 class="relative group"&gt;create table.. partition of语句慢分析
 &lt;div id="create-table-partition-of语句慢分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#create-table-partition-of%e8%af%ad%e5%8f%a5%e6%85%a2%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;59&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;063&lt;/span&gt; CST,&lt;span style="color:#e6db74"&gt;&amp;#34;user1&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;dblzl&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;125889&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;30.88.79.3:37423&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;66461213&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;ebc1,&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;authentication&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;59&lt;/span&gt; CST,&lt;span style="color:#ae81ff"&gt;34&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;41364668&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;,LOG,&lt;span style="color:#ae81ff"&gt;00000&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;connection authorized: user=user1 database=dblzl&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;client backend&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;59&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;079&lt;/span&gt; CST,&lt;span style="color:#e6db74"&gt;&amp;#34;user1&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;dblzl&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;125889&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;30.88.79.3:37423&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;66461213&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;ebc1,&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;59&lt;/span&gt; CST,&lt;span style="color:#ae81ff"&gt;34&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;41364669&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;,LOG,&lt;span style="color:#ae81ff"&gt;00000&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;statement: -- a86fae372f73414bbe1af18213a47beb
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;/*a86fae372f73414bbe1af18213a47beb */
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;create table if not exists table1_partition_p2406 partition of table1 for values from (&amp;#39;2024-06-01 00:00:00&amp;#39;) to (&amp;#39;2024-07-01 00:00:00&amp;#39;); &amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;client backend&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;38&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;28&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;555&lt;/span&gt; CST,&lt;span style="color:#e6db74"&gt;&amp;#34;user1&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;dblzl&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;125889&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;30.88.79.3:37423&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;66461213&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;ebc1,&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;CREATE TABLE&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;59&lt;/span&gt; CST,&lt;span style="color:#ae81ff"&gt;34&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;,LOG,&lt;span style="color:#ae81ff"&gt;00000&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;duration: 2129483.549 ms&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;client backend&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;user1这个用户在22:02:59连接进入数据库后，立即就执行了一个&lt;code&gt;create table.. partition of..&lt;/code&gt;的语句，直到22:38:28才跑完。中间的日志忽略了，一大堆会话阻塞信息，阻塞源均是125889这个会话。
被阻塞的会话类似如下：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;process &lt;span style="color:#ae81ff"&gt;33569&lt;/span&gt; still waiting &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; RowExclusiveLock &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; relation &lt;span style="color:#ae81ff"&gt;53733&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;database&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;17073&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;after&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;048&lt;/span&gt; ms&lt;span style="color:#e6db74"&gt;&amp;#34;,&amp;#34;&lt;/span&gt;Process holding the &lt;span style="color:#66d9ef"&gt;lock&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;125889&lt;/span&gt;. Wait queue: &lt;span style="color:#ae81ff"&gt;33569&lt;/span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;partition of添加分区时，会在主表上加8级锁，然后阻塞分区表上的所有操作。正常来说partition of添加分区是非常快的，锁也会立即释放。不过如果分区表上有长事务，那么这个主表上的8级锁得等着，然后就造成后续的阻塞。
盗&lt;a href="https://blog.csdn.net/qq_40687433/article/details/132525655?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171591065916800225570929%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&amp;amp;request_id=171591065916800225570929&amp;amp;biz_id=0&amp;amp;utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-132525655-null-null.nonecase&amp;amp;utm_term=%E5%88%86%E5%8C%BA%E8%A1%A8&amp;amp;spm=1018.2226.3001.4450" target="_blank" rel="noreferrer"&gt;自己的图&lt;/a&gt;：



&lt;img src="https://lastdba.com/img/csdn/6c7f70fc3b60.png" alt="在这里插入图片描述" /&gt;&lt;/p&gt;
&lt;p&gt;然而这个案例表上没有长事务，partition of添加分区却执行了35分钟。
从历史的进程信息可以看出这个进程是D状态，是有问题的。刚开始以为是内存、磁盘这些问题，排查了一圈都正常。&lt;/p&gt;
&lt;p&gt;然而这个问题很好复现，直接在仿真环境上跑一个&lt;code&gt;create table parttion of&lt;/code&gt;执行会非常慢。pg_stat_activity会话信息显示，该语句等待在IO上：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;wait_event_type &lt;span style="color:#f92672"&gt;|&lt;/span&gt; IO
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;wait_event	 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; DataFileRead
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;state&lt;/span&gt;		&lt;span style="color:#f92672"&gt;|&lt;/span&gt; active
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;query		&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; xxx partition &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; xx &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;values&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2025-05-01 00:00:00&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2025-06-01 00:00:00&amp;#39;&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;strace追踪进程信息发现，该进程大量的读取一个文件&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pread64(&lt;span style="color:#ae81ff"&gt;53&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;\22\2\0\0\220w\321&amp;gt;\0\0\5\0\24\0018\1\0 \4 \0\0\0\0\200\237\0\1\310\236p\1&amp;#34;&lt;/span&gt;..., &lt;span style="color:#ae81ff"&gt;8192&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;863485952&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8192&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;通过文件描述符53找到该文件&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[&lt;span style="color:#f92672"&gt;/&lt;/span&gt;proc&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;356174&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;fd] ll &lt;span style="color:#f92672"&gt;|&lt;/span&gt;grep &lt;span style="color:#ae81ff"&gt;53&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lrwx&lt;span style="color:#75715e"&gt;------ 1 postgres postgres 64 May 17 15:34 53 -&amp;gt; /lzl/pglzl/data/base/17076/25883&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;oid2name &lt;span style="color:#f92672"&gt;-&lt;/span&gt;d lzldb &lt;span style="color:#f92672"&gt;-&lt;/span&gt;f &lt;span style="color:#ae81ff"&gt;25883&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;From&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;database&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;lzldb&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filenode				 &lt;span style="color:#66d9ef"&gt;Table&lt;/span&gt; Name
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-----------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;25883&lt;/span&gt; table_partition_default&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;最后定位这个表table_partition_default&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;d&lt;span style="color:#f92672"&gt;+&lt;/span&gt; table_partition_default
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Partition &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt;: table_partition_default &lt;span style="color:#66d9ef"&gt;DEFAULT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Partition &lt;span style="color:#66d9ef"&gt;constraint&lt;/span&gt;: (&lt;span style="color:#66d9ef"&gt;NOT&lt;/span&gt; ((date_created &lt;span style="color:#66d9ef"&gt;IS&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NOT&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((date_created &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2022-05-01 00:00:00&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;OR&lt;/span&gt; ((date_created &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2022-05-01 00:00:00&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (da
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;dt&lt;span style="color:#f92672"&gt;+&lt;/span&gt; table_partition_default
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; List &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; relations
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Schema&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Name &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Type&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Owner&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Persistence &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Size&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Description 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--------+------------------------------------+-------+------------+-------------+-------+-------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; table_partition_default &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; user1 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; permanent &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;50&lt;/span&gt; GB &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;row&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;原来是default分区表，分区数据有几十GB。oracle dba可能很陌生···pg的default分区会接收不在分区范围中的数据，default分区可以保证即使没有定义到数据范围，也可以接收数据。
如果有数据存在default分区中，新分区又需要包含这部分数据，那这个游戏咋玩呢···直接报错：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;not&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;exists&lt;/span&gt; table_partition_pxxxx partition &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; table_partition &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;values&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-01-12 00:00:00&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-01-13 00:00:00&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ERROR: &lt;span style="color:#ae81ff"&gt;23514&lt;/span&gt;: updated partition &lt;span style="color:#66d9ef"&gt;constraint&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; partition &lt;span style="color:#e6db74"&gt;&amp;#34;table_partition_default&amp;#34;&lt;/span&gt; would be violated &lt;span style="color:#66d9ef"&gt;by&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;some&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;row&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;SCHEMA&lt;/span&gt; NAME: &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;TABLE&lt;/span&gt; NAME: table_partition_default
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;LOCATION&lt;/span&gt;: check_default_partition_contents, partbounds.&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;3227&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;可以看到，添加子分区时，会自动修改default分区的分区约束（Partition constraint）,default分区约束检查即是在做添加普通子分区时的default分区数据校验。&lt;/p&gt;
&lt;p&gt;到这原因已经很明显：
分区表新增子分区时，由于建分区的语句需要校验default分区中的数据，保证新分区数据范围与default分区的现有数据不冲突，导致&lt;code&gt;create table partition of&lt;/code&gt;读取了大量的default分区数据，新建分区一直未完成。随后阻塞扩大，业务数据无法查询和写入。&lt;/p&gt;

&lt;h4 class="relative group"&gt;小结和建议
 &lt;div id="小结和建议" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%b0%8f%e7%bb%93%e5%92%8c%e5%bb%ba%e8%ae%ae" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;postgresql分区表使用的越来越多了，维护分区还有很多需要注意的知识点，推荐看下&lt;a href="https://blog.csdn.net/qq_40687433/article/details/132525655?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171591065916800225570929%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&amp;amp;request_id=171591065916800225570929&amp;amp;biz_id=0&amp;amp;utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-132525655-null-null.nonecase&amp;amp;utm_term=%E5%88%86%E5%8C%BA%E8%A1%A8&amp;amp;spm=1018.2226.3001.4450" target="_blank" rel="noreferrer"&gt;PostgreSQL分区表&lt;/a&gt;，几乎面面俱到。&lt;/p&gt;
&lt;p&gt;在这个案例中，改造关键在于default分区的数据。在default改造前，不要使用partition of方式创建子分区。
default分区改造方案：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;detach default子分区，然后合理创建子分区，再将default表数据回插到分区表中。&lt;/li&gt;
&lt;li&gt;如有必要，可在detach且创建合理子分区后，创建一个空的default分区，以保持业务数据的连续性。&lt;/li&gt;
&lt;li&gt;注意detach跟attach不同，detach需要主表的8级锁。PG14支持detach concurrently。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如不改造default分区，应检查当前default分区的数据范围。再用attach添加子分区，会很慢，但不会阻塞读写。&lt;/p&gt;
&lt;p&gt;最后在复习下分区表新增分区最佳实践：
partition of添加子分区要申请主表的8级锁，风险还是有的。推荐attach方式为表新增子分区（分区索引也可以这么做），不会阻塞读写，完全不影响业务，可在线执行。
&lt;strong&gt;分区表添加新分区的正确姿势&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;CREATE&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;TABLE&lt;/span&gt; lzlpartition1_202303
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#66d9ef"&gt;LIKE&lt;/span&gt; lzlpartition1 &lt;span style="color:#66d9ef"&gt;INCLUDING&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;DEFAULTS&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;INCLUDING&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;CONSTRAINTS&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;alter&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; LZLPARTITION1 attach partition LZLPARTITION1_202303 &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;values&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-03-01 00:00:00&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-04-01 00:00:00&amp;#39;&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;如果新分区还有数据的话，attach还可能比较慢，可提前创建约束来优化
&lt;strong&gt;分区表添加有数据分区的正确姿势&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--减少繁琐的ddl，like方式创建表
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;CREATE&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;TABLE&lt;/span&gt; lzlpartition1_202303
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#66d9ef"&gt;LIKE&lt;/span&gt; lzlpartition1 &lt;span style="color:#66d9ef"&gt;INCLUDING&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;DEFAULTS&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;INCLUDING&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;CONSTRAINTS&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--无数据可忽略该步骤。参考其他分区的Partition constraint，添加表的check约束，减少attach检查约束的时间。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;alter&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; lzlpartition1_202303 &lt;span style="color:#66d9ef"&gt;add&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;constraint&lt;/span&gt; chk_202303 &lt;span style="color:#66d9ef"&gt;CHECK&lt;/span&gt; ((date_created &lt;span style="color:#66d9ef"&gt;IS&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NOT&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (date_created &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2023-03-01 00:00:00&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (date_created &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2023-04-01 00:00:00&amp;#39;&lt;/span&gt;::&lt;span style="color:#66d9ef"&gt;timestamp&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;without&lt;/span&gt; time &lt;span style="color:#66d9ef"&gt;zone&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--attach方式添加分区
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;alter&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; LZLPARTITION1 attach partition LZLPARTITION1_202303 &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;values&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-03-01 00:00:00&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;2023-04-01 00:00:00&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--可选。在新分区有事务之前，删除多余的check约束
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;alter&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; lzlpartition1_202303 &lt;span style="color:#66d9ef"&gt;drop&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;constraint&lt;/span&gt; chk_202303;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded></item><item><title>我要查的表没有在执行计划中</title><link>https://lastdba.com/2024/08/12/%E6%88%91%E8%A6%81%E6%9F%A5%E7%9A%84%E8%A1%A8%E6%B2%A1%E6%9C%89%E5%9C%A8%E6%89%A7%E8%A1%8C%E8%AE%A1%E5%88%92%E4%B8%AD/</link><pubDate>Mon, 12 Aug 2024 00:00:00 +0000</pubDate><guid>https://lastdba.com/2024/08/12/%E6%88%91%E8%A6%81%E6%9F%A5%E7%9A%84%E8%A1%A8%E6%B2%A1%E6%9C%89%E5%9C%A8%E6%89%A7%E8%A1%8C%E8%AE%A1%E5%88%92%E4%B8%AD/</guid><description>&lt;h2 class="relative group"&gt;问题：查的表没有在执行计划中
 &lt;div id="问题查的表没有在执行计划中" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e6%9f%a5%e7%9a%84%e8%a1%a8%e6%b2%a1%e6%9c%89%e5%9c%a8%e6%89%a7%e8%a1%8c%e8%ae%a1%e5%88%92%e4%b8%ad" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;sql：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; A.column1 &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;column1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;--中间省略很多A字段
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; A.column99 &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;column99&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; table_a A
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;left&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;join&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; lzl_id
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; table_a AA
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;inner&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;join&lt;/span&gt; table_b BB &lt;span style="color:#66d9ef"&gt;ON&lt;/span&gt; AA.lzl_key &lt;span style="color:#f92672"&gt;=&lt;/span&gt; BB.lzl_id
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; AA.column_code &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;GROUP&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;BY&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; lzl_id
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ) B &lt;span style="color:#66d9ef"&gt;ON&lt;/span&gt; B.lzl_id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; A.lzl_key
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; A.flagflagflag &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; A.typetypetype &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ) TEMP
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;limit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;offset&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;执行计划：&lt;/p&gt;</description><content:encoded>
&lt;h2 class="relative group"&gt;问题：查的表没有在执行计划中
 &lt;div id="问题查的表没有在执行计划中" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%97%ae%e9%a2%98%e6%9f%a5%e7%9a%84%e8%a1%a8%e6%b2%a1%e6%9c%89%e5%9c%a8%e6%89%a7%e8%a1%8c%e8%ae%a1%e5%88%92%e4%b8%ad" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;sql：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; A.column1 &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;column1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;--中间省略很多A字段
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; A.column99 &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;column99&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; table_a A
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;left&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;join&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; lzl_id
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; table_a AA
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;inner&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;join&lt;/span&gt; table_b BB &lt;span style="color:#66d9ef"&gt;ON&lt;/span&gt; AA.lzl_key &lt;span style="color:#f92672"&gt;=&lt;/span&gt; BB.lzl_id
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; AA.column_code &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;GROUP&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;BY&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; lzl_id
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ) B &lt;span style="color:#66d9ef"&gt;ON&lt;/span&gt; B.lzl_id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; A.lzl_key
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; A.flagflagflag &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; A.typetypetype &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ) TEMP
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;limit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;offset&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;执行计划：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;----------------------------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Limit&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;84&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;68&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1105&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;038&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;039&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Seq Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; table_a a (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;84&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1105&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;036&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;037&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (((flagflagflag)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((typetypetype)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Rows&lt;/span&gt; Removed &lt;span style="color:#66d9ef"&gt;by&lt;/span&gt; Filter: &lt;span style="color:#ae81ff"&gt;38&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;184&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Execution Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;066&lt;/span&gt; ms&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;可以看到，sql本身是比较复杂的，SQL的逻辑查了3次表，总共查了2张表。table_a 在执行计划中我可以理解，但是需要查的table_b根本没在执行计划里面！这个执行计划只不过是简单的全表扫描了table_a。&lt;/p&gt;

&lt;h2 class="relative group"&gt;分析的心路历程
 &lt;div id="分析的心路历程" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%88%86%e6%9e%90%e7%9a%84%e5%bf%83%e8%b7%af%e5%8e%86%e7%a8%8b" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;中间其实想过很多可能，不过最有可能的是逻辑优化了，也就是说pg优化器认为table_b不需要查。
观察sql发现sql最终只查询了table_a的字段，没有查table_b。此时任意增加一个中间表B的字段，sql执行计划看上去就“正常”了，访问了table_b&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; A.column1 &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;column1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;--中间省略很多A字段
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; A.column99 &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;column99&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; B.lzl_id &lt;span style="color:#75715e"&gt;--新增一个B中间表的字段
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; table_a A
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;left&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;join&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; lzl_id
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; table_a AA
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;inner&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;join&lt;/span&gt; table_b BB &lt;span style="color:#66d9ef"&gt;ON&lt;/span&gt; AA.lzl_key &lt;span style="color:#f92672"&gt;=&lt;/span&gt; BB.lzl_id
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; AA.column_code &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;GROUP&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;BY&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; lzl_id
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ) B &lt;span style="color:#66d9ef"&gt;ON&lt;/span&gt; B.lzl_id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; A.lzl_key
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; A.flagflagflag &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; A.typetypetype &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ) TEMP
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;limit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;offset&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;---------------------------------------------------------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Limit&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;69&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;17&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;67&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1113&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Nested Loop &lt;span style="color:#66d9ef"&gt;Left&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Join&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;72&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;69&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1113&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Join&lt;/span&gt; Filter: (bb.lzl_id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; a.lzl_key)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Seq Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; table_a a (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;84&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1113&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (((flagflagflag)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;::text) &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; ((typetypetype)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Group&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;72&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;74&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Group&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Key&lt;/span&gt;: bb.lzl_id
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Sort (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;72&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;73&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Sort &lt;span style="color:#66d9ef"&gt;Key&lt;/span&gt;: bb.lzl_id
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Nested Loop (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;66&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Seq Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; table_a aa (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;70&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: ((company_code)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Only&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_table_b_lzl_id &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; table_b bb (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;83&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;13&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (lzl_id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; aa.lzl_key)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这看上去跟left join有关系，但是简单想想又不对，因为右表的结果是会影响查询的最终结果的，不应该不去查右表。随便来个简单的left join，右表会被扫描&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; lzlleft.a &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzlleft &lt;span style="color:#66d9ef"&gt;left&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;join&lt;/span&gt; lzlright &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzlleft.a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;lzlright.a;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Hash &lt;span style="color:#66d9ef"&gt;Left&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Join&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;47&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;320&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Hash Cond: (lzlleft.a &lt;span style="color:#f92672"&gt;=&lt;/span&gt; lzlright.a)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Seq Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzlleft (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;13&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;320&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Hash (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Seq Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzlright (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;但是，在中间表B中，有个关键字&lt;code&gt;GROUP BY&lt;/code&gt;。如果把&lt;code&gt;GROUP BY&lt;/code&gt;去掉，那么无论有没有查询B的字段，都会访问table_b。
我们再在测试表中加个group by看看结果&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzlleft;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; a &lt;span style="color:#f92672"&gt;|&lt;/span&gt; b 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;---+-----
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; zzz
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;row&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;259&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzlright;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; a &lt;span style="color:#f92672"&gt;|&lt;/span&gt; b 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;---+-------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; qwer
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; poiuy 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; lzlright.b &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzlleft &lt;span style="color:#66d9ef"&gt;full&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;join&lt;/span&gt; lzlright &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzlleft.b&lt;span style="color:#f92672"&gt;=&lt;/span&gt;lzlright.b &lt;span style="color:#66d9ef"&gt;group&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;by&lt;/span&gt; lzlright.b;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; b 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; poiuy
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; qwer
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这里就意识到了group by出来的结果集一定有一个特性——&lt;strong&gt;唯一性&lt;/strong&gt;。
我们再在测表里加group by&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; lzlleft.a &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzlleft &lt;span style="color:#66d9ef"&gt;left&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;join&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; a &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzlright &lt;span style="color:#66d9ef"&gt;group&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;by&lt;/span&gt; a) &lt;span style="color:#66d9ef"&gt;c&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzlleft.a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;.a;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;----------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Seq Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzlleft (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;13&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;320&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;右表不查了！
根据右表唯一性的原则，下面还可以有一些骚操作：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--distinct确保右表唯一
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; lzlleft.a &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzlleft &lt;span style="color:#66d9ef"&gt;left&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;join&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;distinct&lt;/span&gt; a &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzlright) &lt;span style="color:#66d9ef"&gt;c&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzlleft.a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;.a;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;----------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Seq Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzlleft (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;13&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;320&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--唯一索引确保右表唯一，哪怕是select a from lzlright
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; explain select lzlleft.a from lzlleft left join (select a from lzlright) c on lzlleft.a=c.a;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-----------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Hash Left Join (cost=17.20..49.12 rows=512 width=4)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Hash Cond: (lzlleft.a = lzlright.a)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Seq Scan on lzlleft (cost=0.00..13.20 rows=320 width=4)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Hash (cost=13.20..13.20 rows=320 width=4)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Seq Scan on lzlright (cost=0.00..13.20 rows=320 width=4)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(5 rows)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Time: 0.510 ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; create unique index idx_right on lzlright(a);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CREATE INDEX
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Time: 3.576 ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; explain select lzlleft.a from lzlleft left join (select a from lzlright) c on lzlleft.a=c.a;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Seq Scan on lzlleft (cost=0.00..13.20 rows=320 width=4)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(1 row)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;到这里来个分析小结：只要右表的数据是唯一的且只查询左表数据时，不需要真的去访问右表 。所以这不是一个bug，而是PG优化器的特性，是符合逻辑的。&lt;/p&gt;

&lt;h2 class="relative group"&gt;源码分析
 &lt;div id="源码分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%ba%90%e7%a0%81%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;本期没有源码分析~
优化器源码实在太难了，这里就找了下优化器源码的注释看了下。可以搜索关键字&lt;code&gt;unique-ify&lt;/code&gt;，有这么一句话：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; Also, this routine and others in this module accept the special JoinTypes
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; JOIN_UNIQUE_OUTER and JOIN_UNIQUE_INNER to indicate that we should
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; unique&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ify the outer or inner relation and then apply a regular inner
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; join. These values are not allowed to propagate outside this module,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; however. Path cost estimation code may need to recognize that it&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&lt;/span&gt;s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; dealing with such a &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#f92672"&gt;---&lt;/span&gt; the combination of nominal jointype INNER
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; with sjinfo&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;jointype &lt;span style="color:#f92672"&gt;==&lt;/span&gt; JOIN_SEMI indicates that. 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;特殊的JoinTypes：JOIN_UNIQUE_INNER 和JOIN_UNIQUE_OUTER ，尝试把外表和内表连接唯一化后，成为inner join。Path代价估算需要考虑这种场景。&lt;/p&gt;

&lt;h2 class="relative group"&gt;与oracle、mysql优化器的对比
 &lt;div id="与oraclemysql优化器的对比" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%b8%8eoraclemysql%e4%bc%98%e5%8c%96%e5%99%a8%e7%9a%84%e5%af%b9%e6%af%94" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;对比看下oracle、mysql优化器有没有类似的逻辑优化提升&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--oracle
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; lzlleft(a number);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; lzlright(a number);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; lzlleft.a &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzlleft &lt;span style="color:#66d9ef"&gt;left&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;join&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;distinct&lt;/span&gt; a &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzlright) &lt;span style="color:#66d9ef"&gt;c&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzlleft.a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;.a;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--group by 唯一性
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;SQL&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; lzlleft.a &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzlleft &lt;span style="color:#66d9ef"&gt;left&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;join&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; a &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzlright &lt;span style="color:#66d9ef"&gt;group&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;by&lt;/span&gt; a) &lt;span style="color:#66d9ef"&gt;c&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzlleft.a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;.a; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;no&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt; selected
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Execution Plan
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;----------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Plan hash value: &lt;span style="color:#ae81ff"&gt;3533354041&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;---------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; Id &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Operation&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Name &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Rows&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Bytes &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Cost (&lt;span style="color:#f92672"&gt;%&lt;/span&gt;CPU)&lt;span style="color:#f92672"&gt;|&lt;/span&gt; Time &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;---------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;STATEMENT&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;)&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; HASH &lt;span style="color:#66d9ef"&gt;JOIN&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;OUTER&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;)&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;TABLE&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ACCESS&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;FULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; LZLLEFT &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;VIEW&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;34&lt;/span&gt;)&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; HASH &lt;span style="color:#66d9ef"&gt;GROUP&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;BY&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;34&lt;/span&gt;)&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;TABLE&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ACCESS&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;FULL&lt;/span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; LZLRIGHT &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;---------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Predicate Information (identified &lt;span style="color:#66d9ef"&gt;by&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;operation&lt;/span&gt; id):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;access&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;LZLLEFT&amp;#34;&lt;/span&gt;.&lt;span style="color:#e6db74"&gt;&amp;#34;A&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;C&amp;#34;&lt;/span&gt;.&lt;span style="color:#e6db74"&gt;&amp;#34;A&amp;#34;&lt;/span&gt;(&lt;span style="color:#f92672"&gt;+&lt;/span&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--ditinct 唯一 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;SQL&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; lzlleft.a &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzlleft &lt;span style="color:#66d9ef"&gt;left&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;join&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;distinct&lt;/span&gt; a &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzlright) &lt;span style="color:#66d9ef"&gt;c&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzlleft.a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;.a;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;no&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt; selected
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Execution Plan
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;----------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Plan hash value: &lt;span style="color:#ae81ff"&gt;3859658234&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;---------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; Id &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Operation&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Name &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Rows&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Bytes &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Cost (&lt;span style="color:#f92672"&gt;%&lt;/span&gt;CPU)&lt;span style="color:#f92672"&gt;|&lt;/span&gt; Time &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;---------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;STATEMENT&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;)&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; HASH &lt;span style="color:#66d9ef"&gt;JOIN&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;OUTER&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;)&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;TABLE&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ACCESS&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;FULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; LZLLEFT &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;VIEW&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;34&lt;/span&gt;)&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; HASH &lt;span style="color:#66d9ef"&gt;UNIQUE&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;34&lt;/span&gt;)&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;TABLE&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ACCESS&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;FULL&lt;/span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; LZLRIGHT &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;---------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Predicate Information (identified &lt;span style="color:#66d9ef"&gt;by&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;operation&lt;/span&gt; id):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;access&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;LZLLEFT&amp;#34;&lt;/span&gt;.&lt;span style="color:#e6db74"&gt;&amp;#34;A&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;C&amp;#34;&lt;/span&gt;.&lt;span style="color:#e6db74"&gt;&amp;#34;A&amp;#34;&lt;/span&gt;(&lt;span style="color:#f92672"&gt;+&lt;/span&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--mysql 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; lzlleft(a int &lt;span style="color:#66d9ef"&gt;primary&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;key&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;create&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; lzlright(a int &lt;span style="color:#66d9ef"&gt;primary&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;key&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--group by唯一
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; lzlleft.a &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzlleft &lt;span style="color:#66d9ef"&gt;left&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;join&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; a &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzlright &lt;span style="color:#66d9ef"&gt;group&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;by&lt;/span&gt; a) &lt;span style="color:#66d9ef"&gt;c&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzlleft.a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;.a; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#75715e"&gt;----+-------------+------------+------------+-------+---------------+-------------+---------+-----------------+------+----------+-------------+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; id &lt;span style="color:#f92672"&gt;|&lt;/span&gt; select_type &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; partitions &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; possible_keys &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;key&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; key_len &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ref&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; filtered &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Extra &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#75715e"&gt;----+-------------+------------+------------+-------+---------------+-------------+---------+-----------------+------+----------+-------------+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzlleft &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Using&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;derived2&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ref&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;auto_key0&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;auto_key0&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzldb.lzlleft.a &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Using&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; DERIVED &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzlright &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Using&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#75715e"&gt;----+-------------+------------+------------+-------+---------------+-------------+---------+-----------------+------+----------+-------------+&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--distinct唯一
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; lzlleft.a &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzlleft &lt;span style="color:#66d9ef"&gt;left&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;join&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;distinct&lt;/span&gt; a &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; lzlright) &lt;span style="color:#66d9ef"&gt;c&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; lzlleft.a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;c&lt;/span&gt;.a;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#75715e"&gt;----+-------------+------------+------------+-------+---------------+-------------+---------+-----------------+------+----------+-------------+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; id &lt;span style="color:#f92672"&gt;|&lt;/span&gt; select_type &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;table&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; partitions &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; possible_keys &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;key&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; key_len &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ref&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; filtered &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Extra &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#75715e"&gt;----+-------------+------------+------------+-------+---------------+-------------+---------+-----------------+------+----------+-------------+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzlleft &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Using&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;derived2&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ref&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;auto_key0&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;auto_key0&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzldb.lzlleft.a &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Using&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; DERIVED &lt;span style="color:#f92672"&gt;|&lt;/span&gt; lzlright &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Using&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;index&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#75715e"&gt;----+-------------+------------+------------+-------+---------------+-------------+---------+-----------------+------+----------+-------------+&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;综上，oracle、mysql均不会对left join只查左表且右表唯一做优化，他们会访问右表。
pg优化器确实是有些东西的。&lt;/p&gt;</content:encoded></item><item><title>长事务、表膨胀、limit问题的一个经典案例</title><link>https://lastdba.com/2024/08/12/%E9%95%BF%E4%BA%8B%E5%8A%A1%E8%A1%A8%E8%86%A8%E8%83%80limit%E9%97%AE%E9%A2%98%E7%9A%84%E4%B8%80%E4%B8%AA%E7%BB%8F%E5%85%B8%E6%A1%88%E4%BE%8B/</link><pubDate>Mon, 12 Aug 2024 00:00:00 +0000</pubDate><guid>https://lastdba.com/2024/08/12/%E9%95%BF%E4%BA%8B%E5%8A%A1%E8%A1%A8%E8%86%A8%E8%83%80limit%E9%97%AE%E9%A2%98%E7%9A%84%E4%B8%80%E4%B8%AA%E7%BB%8F%E5%85%B8%E6%A1%88%E4%BE%8B/</guid><description>&lt;h1 class="relative group"&gt;update主键慢，问题分析
 &lt;div id="update主键慢问题分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#update%e4%b8%bb%e9%94%ae%e6%85%a2%e9%97%ae%e9%a2%98%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h1&gt;
&lt;p&gt;一个简单的主键更新，update执行了超过1s，由于并发比较高，cpu直接打满&lt;/p&gt;</description><content:encoded>
&lt;h1 class="relative group"&gt;update主键慢，问题分析
 &lt;div id="update主键慢问题分析" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#update%e4%b8%bb%e9%94%ae%e6%85%a2%e9%97%ae%e9%a2%98%e5%88%86%e6%9e%90" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h1&gt;
&lt;p&gt;一个简单的主键更新，update执行了超过1s，由于并发比较高，cpu直接打满&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;19&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;36&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;084&lt;/span&gt; CST,&lt;span style="color:#e6db74"&gt;&amp;#34;lzlopr&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;lzl&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;158751&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;10.33.78.149:51502&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;66055&lt;/span&gt;a6b.&lt;span style="color:#ae81ff"&gt;26&lt;/span&gt;c1f,&lt;span style="color:#ae81ff"&gt;172&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;UPDATE&amp;#34;&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;03&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;28&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;19&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;54&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;19&lt;/span&gt; CST,&lt;span style="color:#ae81ff"&gt;528&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;19816630&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;970251337&lt;/span&gt;,LOG,&lt;span style="color:#ae81ff"&gt;00000&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;duration: 1218.688 ms plan:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;Query Text: update table_a set (省略...）=$6 where column_id =$7
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;Update on table_a (cost=0.40..5.49 rows=1 width=2774)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;-&amp;gt; Index Scan using pk_id on table_a (cost=0.40..5.49 rows=1 width=2774)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; Index Cond: ((column_id)::text = $7)&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;PostgreSQL JDBC Driver&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;client backend&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;sql本身也非常简单，就是条件为=&amp;lsquo;主键&amp;rsquo;的更新。看update的执行计划，是走了pk主键索引的，所以从执行计划上看没有问题，问题不在执行计划突变。&lt;/p&gt;
&lt;p&gt;改写下sql（因为是update），&lt;code&gt;explain (analyze,buffers)&lt;/code&gt;对比看下SQL的执行消耗&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt;,buffers) &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; table_a &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; column_id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;d4f713370e584820a9b15e2218ea436a&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;---------------------------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Bitmap Heap Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; table_a (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;91&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;42&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1156&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;55&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;052&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;123&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;354&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Recheck&lt;/span&gt; Cond: ((column_id)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;d4f713370e584820a9b15e2218ea436a&amp;#39;&lt;/span&gt;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Heap Blocks: exact&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;13870&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Bitmap &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; pk_id (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;91&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;464&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;465&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;13866&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((column_id)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;d4f713370e584820a9b15e2218ea436a&amp;#39;&lt;/span&gt;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4261&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning Time: &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;028&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Execution Time: &lt;span style="color:#ae81ff"&gt;123&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;567&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;11&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这里的真实执行计划没问题，但是shared hit=13870明显太高了。正常来说走主键不应该扫描太多的page，这里比较容易联想到表膨胀&lt;/p&gt;
&lt;p&gt;查看表膨胀：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--表大小 \dt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Size&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;525&lt;/span&gt; MB&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--表的实际行数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;count&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;827&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--死元组 pg_stat_all_tables
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n_live_tup &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;786&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n_dead_tup &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;657604&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;有只有800条活元组，但是有65w条死元组！主键扫描了多个page的原因应该就是这个，但是为啥没有回收死元组呢？
表在默认修改20%数据的时候就会触发autovacuum执行vacuum回收，这个在日志中可以看到，autovacuum是有被触发的：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-04-01 14:13:46.649 CST,,,14081,,660a5099.3701,1,,2024-04-01 14:13:45 CST,259/17828993,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;automatic vacuum of table &amp;#34;&amp;#34;lzl.public.table_a&amp;#34;&amp;#34;: index scans: 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;2024-04-01 14:13:47.801 CST,,,14081,,660a5099.3701,2,,2024-04-01 14:13:45 CST,259/17828994,971045014,LOG,00000,&amp;#34;&lt;/span&gt;automatic analyze of table &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;lzl.public.table_a&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt; system usage: CPU: user: 0.08 s, system: 0.01 s, elapsed: 1.15 s&lt;span style="color:#e6db74"&gt;&amp;#34;,,,,,,,,,&amp;#34;&amp;#34;,&amp;#34;&lt;/span&gt;autovacuum worker&lt;span style="color:#e6db74"&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;2024-04-01 14:14:46.673 CST,,,26136,,660a50d5.6618,1,,2024-04-01 14:14:45 CST,259/17829090,0,LOG,00000,&amp;#34;&lt;/span&gt;automatic vacuum of table &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;lzl.public.table_a&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;: index scans: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-04-01 14:14:47.833 CST,,,26136,,660a50d5.6618,2,,2024-04-01 14:14:45 CST,259/17829091,971049759,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;automatic analyze of table &amp;#34;&amp;#34;lzl.public.table_a&amp;#34;&amp;#34; system usage: CPU: user: 0.08 s, system: 0.03 s, elapsed: 1.15 s&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;autovacuum worker&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-04-01 14:15:46.680 CST,,,40743,,660a5111.9f27,1,,2024-04-01 14:15:45 CST,259/17829164,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;automatic vacuum of table &amp;#34;&amp;#34;lzl.public.table_a&amp;#34;&amp;#34;: index scans: 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;2024-04-01 14:15:47.849 CST,,,40743,,660a5111.9f27,2,,2024-04-01 14:15:45 CST,259/17829165,971055464,LOG,00000,&amp;#34;&lt;/span&gt;automatic analyze of table &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;lzl.public.table_a&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt; system usage: CPU: user: 0.08 s, system: 0.03 s, elapsed: 1.16 s&lt;span style="color:#e6db74"&gt;&amp;#34;,,,,,,,,,&amp;#34;&amp;#34;,&amp;#34;&lt;/span&gt;autovacuum worker&lt;span style="color:#e6db74"&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;2024-04-01 14:16:46.677 CST,,,52599,,660a514d.cd77,1,,2024-04-01 14:16:45 CST,259/17829263,0,LOG,00000,&amp;#34;&lt;/span&gt;automatic vacuum of table &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;lzl.public.table_a&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;: index scans: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-04-01 14:16:47.844 CST,,,52599,,660a514d.cd77,2,,2024-04-01 14:16:45 CST,259/17829264,971061382,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;automatic analyze of table &amp;#34;&amp;#34;lzl.public.table_a&amp;#34;&amp;#34; system usage: CPU: user: 0.08 s, system: 0.03 s, elapsed: 1.16 s&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;autovacuum worker&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-04-01 14:17:46.699 CST,,,64858,,660a5189.fd5a,1,,2024-04-01 14:17:45 CST,234/16589539,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;automatic vacuum of table &amp;#34;&amp;#34;lzl.public.table_a&amp;#34;&amp;#34;: index scans: 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;2024-04-01 14:17:47.851 CST,,,64858,,660a5189.fd5a,2,,2024-04-01 14:17:45 CST,234/16589540,971066091,LOG,00000,&amp;#34;&lt;/span&gt;automatic analyze of table &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;lzl.public.table_a&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt; system usage: CPU: user: 0.09 s, system: 0.02 s, elapsed: 1.15 s&lt;span style="color:#e6db74"&gt;&amp;#34;,,,,,,,,,&amp;#34;&amp;#34;,&amp;#34;&lt;/span&gt;autovacuum worker&lt;span style="color:#e6db74"&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;2024-04-01 14:18:46.703 CST,,,78112,,660a51c5.13120,1,,2024-04-01 14:18:45 CST,259/17829409,0,LOG,00000,&amp;#34;&lt;/span&gt;automatic vacuum of table &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;lzl.public.table_a&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;: index scans: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-04-01 14:18:47.854 CST,,,78112,,660a51c5.13120,2,,2024-04-01 14:18:45 CST,259/17829410,971070390,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;automatic analyze of table &amp;#34;&amp;#34;lzl.public.table_a&amp;#34;&amp;#34; system usage: CPU: user: 0.09 s, system: 0.02 s, elapsed: 1.15 s&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;autovacuum worker&amp;#34;&lt;/span&gt;		&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;不仅有触发，而且间隔刚好是一分钟。autovacuum_naptime间隔触发时间默认就是1分钟&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;show&lt;/span&gt; autovacuum_naptime ;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; autovacuum_naptime 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;min&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;row&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;可以判断：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;autovacuum成功触发&lt;/li&gt;
&lt;li&gt;死元组可能回收不及，1分钟内产生的死元组大于20%（可能1分钟太长了）；或者根本没有回收，下次一定触发autovacuum&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;看下autovacuum的具体内容：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2024-04-01 10:22:44.648 CST,,,16827,,660a1a73.41bb,1,,2024-04-01 10:22:43 CST,170/16910186,0,LOG,00000,&lt;span style="color:#e6db74"&gt;&amp;#34;automatic vacuum of table &amp;#34;&amp;#34;lzl.public.table_a&amp;#34;&amp;#34;: index scans: 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;pages: 0 removed, 48745 remain, 6 skipped due to pins, 0 skipped frozen
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;tuples: 0 removed, 744488 remain, 743666 are dead but not yet removable, oldest xmin: 969118077
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;buffer usage: 97603 hits, 0 misses, 5 dirtied
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;avg read rate: 0.000 MB/s, avg write rate: 0.028 MB/s
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;system usage: CPU: user: 0.21 s, system: 0.22 s, elapsed: 1.41 s
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;WAL usage: 4 records, 3 full page images, 5129 bytes&amp;#34;&lt;/span&gt;,,,,,,,,,&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;autovacuum worker&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;autovacuum触发了，但是完全没有回收死元组&lt;code&gt;tuples: 0 removed, 744488 remain, 743666 are dead but not yet removable, oldest xmin: 969118077&lt;/code&gt;。&lt;code&gt;oldest xmin&lt;/code&gt;代表库内的最旧事务，也就是有长事务，这个很好找到：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; pid,usename,xact_start,state_change,wait_event,&lt;span style="color:#66d9ef"&gt;state&lt;/span&gt;,query &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; pg_stat_activity &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;state&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;idle&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;order&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;by&lt;/span&gt; xact_start ;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pid &lt;span style="color:#f92672"&gt;|&lt;/span&gt; usename &lt;span style="color:#f92672"&gt;|&lt;/span&gt; xact_start &lt;span style="color:#f92672"&gt;|&lt;/span&gt; state_change &lt;span style="color:#f92672"&gt;|&lt;/span&gt; wait_event &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--------+------------+-------------------------------+-------------------------------+---------------------+---------------------+------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;164658&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; phbdspsqp &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;08&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;36&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;57&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;275408&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;08&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;36&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;57&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;299609&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; DataFileRead &lt;span style="color:#f92672"&gt;|&lt;/span&gt; active &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;minval&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;maxval&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;min&lt;/span&gt;(ID) &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; minval,&lt;span style="color:#66d9ef"&gt;max&lt;/span&gt;(TRACK&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;长事务就是这个早上8点多跑了几个小时sql。虽然不是一个表，但是因为是&lt;code&gt;oldest xmin&lt;/code&gt;所以也会有影响。
至此原因已经定位：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;表A的update频繁，表膨胀风险较高&lt;/li&gt;
&lt;li&gt;表B长事务阻止表A死元组回收&lt;/li&gt;
&lt;li&gt;表A的update语句扫描了过多的page&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;解决办法：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;结束长事务。&lt;code&gt;select pg_terminate_backend(164658)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;手动vacuum或者等待1分钟（以内）自动vacuum。 &lt;code&gt;vacuum table_a&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上面2个操作完成后，查看死元组&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n_live_tup &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;707&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n_dead_tup &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;298&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;65w的死元组已清理。
再次查看执行计划：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;analyze&lt;/span&gt;,buffers) &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; table_a &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; column_id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;d4f713370e584820a9b15e2218ea436a&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-------------------------------------------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; pk_id &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; table_a (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;40&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;44&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;621&lt;/span&gt;) (actual time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;026&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;029&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; loops&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((column_id)::text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;d4f713370e584820a9b15e2218ea436a&amp;#39;&lt;/span&gt;::text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Buffers: shared hit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Planning Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;057&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Execution Time: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;043&lt;/span&gt; ms&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;shared hit只有6，故障恢复。&lt;/p&gt;
&lt;p&gt;另外，vacuum只会回收死元组，但是不会清理空间，表还是那么大。这个只有等新数据复用空间或者repack等重建表的操作来回收&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Size&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;525&lt;/span&gt; MB&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 class="relative group"&gt;order by limit的番外sql优化：
 &lt;div id="order-by-limit的番外sql优化" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#order-by-limit%e7%9a%84%e7%95%aa%e5%a4%96sql%e4%bc%98%e5%8c%96" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h1&gt;
&lt;p&gt;刚才那个长事务sql，也有问题···
业务反馈前几天都快，今天跑了几个小时了&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;min&lt;/span&gt;(ID) &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; minval,&lt;span style="color:#66d9ef"&gt;max&lt;/span&gt;(ID) &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; maxval &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; table_b &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; time_at &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; to_timestamp(&lt;span style="color:#e6db74"&gt;&amp;#39;2024-03-30 00:00:00&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;yyyy-MM-dd HH24:mi:ss&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;--------------------------------------------------------------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Result&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4298&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;54&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;4298&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;55&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;64&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; InitPlan &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;returns&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Limit&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;70&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;2149&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; pk_b &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; table_b (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;70&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;1181490202&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;549896&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((ID)::text &lt;span style="color:#66d9ef"&gt;IS&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NOT&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (time_at &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; to_timestamp(&lt;span style="color:#e6db74"&gt;&amp;#39;2024-03-30 00:00:00&amp;#39;&lt;/span&gt;::text, &lt;span style="color:#e6db74"&gt;&amp;#39;yyyy-MM-dd HH24:mi:ss&amp;#39;&lt;/span&gt;::text))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; InitPlan &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;returns&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Limit&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;70&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;2149&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;Backward&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; pk_b &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; table_b table_b_1 (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;70&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;1181490202&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;549896&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: ((ID)::text &lt;span style="color:#66d9ef"&gt;IS&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NOT&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Filter: (time_at &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; to_timestamp(&lt;span style="color:#e6db74"&gt;&amp;#39;2024-03-30 00:00:00&amp;#39;&lt;/span&gt;::text, &lt;span style="color:#e6db74"&gt;&amp;#39;yyyy-MM-dd HH24:mi:ss&amp;#39;&lt;/span&gt;::text))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;sql也很简单，条件只有一个时间字段 ，过滤性还可以
不过这个sql没有走 time_at 索引，而是走的 ID主键索引 。这个跟&lt;a href="https://blog.csdn.net/qq_40687433/article/details/134387782?spm=1001.2014.3001.5501" target="_blank" rel="noreferrer"&gt;limit问题&lt;/a&gt;是一样的。analyze是没有用的，最好是改写sql。
改写后SQL结果秒出：&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;explain&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;min&lt;/span&gt;(ID&lt;span style="color:#f92672"&gt;||&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; minval,&lt;span style="color:#66d9ef"&gt;max&lt;/span&gt;(ID&lt;span style="color:#f92672"&gt;||&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; maxval &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; table_b &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; time_at &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; to_timestamp(&lt;span style="color:#e6db74"&gt;&amp;#39;2024-03-30 00:00:00&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;yyyy-MM-dd HH24:mi:ss&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QUERY PLAN 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;----------------------------------------------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Aggregate&lt;/span&gt; (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1201418&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;86&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;1201418&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;87&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;64&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Scan &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; idx_time_at &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; table_b (cost&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;57&lt;/span&gt;..&lt;span style="color:#ae81ff"&gt;1195919&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;90&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;549896&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;33&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Index&lt;/span&gt; Cond: (time_at &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; to_timestamp(&lt;span style="color:#e6db74"&gt;&amp;#39;2024-03-30 00:00:00&amp;#39;&lt;/span&gt;::text, &lt;span style="color:#e6db74"&gt;&amp;#39;yyyy-MM-dd HH24:mi:ss&amp;#39;&lt;/span&gt;::text))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这个还不是执行计划突变，因为没有变。前几天同样是这样的执行计划，但是跑的比较快，原因是还是因为数据分布和limit的机制，数据很快就找到自然就返回了，这也是优化器为什么会选择主键索引；“运气不好”数据半天找不到就要跑很久。&lt;/p&gt;

&lt;h2 class="relative group"&gt;小结
 &lt;div id="小结" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%b0%8f%e7%bb%93" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;一个经典的案例：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;update频繁更新的小表&lt;/li&gt;
&lt;li&gt;长事务阻止死元组回收&lt;/li&gt;
&lt;li&gt;长事务是排序和limt操作（order by，max/min，group都有可能）导致的索引选择问题&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一个故障，三个postgres的经典知识点，相当有代表性。&lt;/p&gt;</content:encoded></item></channel></rss>