Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wWcxQ-002kLA-2S for pgsql-hackers@arkaria.postgresql.org; Mon, 08 Jun 2026 16:36:12 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wWcxO-003F4P-30 for pgsql-hackers@arkaria.postgresql.org; Mon, 08 Jun 2026 16:36:10 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wWcxO-003F4G-1e for pgsql-hackers@lists.postgresql.org; Mon, 08 Jun 2026 16:36:10 +0000 Received: from mail-ej1-x634.google.com ([2a00:1450:4864:20::634]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wWcxM-00000001iI1-1HV6 for pgsql-hackers@lists.postgresql.org; Mon, 08 Jun 2026 16:36:09 +0000 Received: by mail-ej1-x634.google.com with SMTP id a640c23a62f3a-bef47b1ac01so687185166b.2 for ; Mon, 08 Jun 2026 09:36:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1780936566; cv=none; d=google.com; s=arc-20240605; b=JbYmOHi+nj6tcbB85qIQ3pk9l1CyoAoy2YLOIoRF9F1jsplwDmOds0ajTwgdIonEmU OTPNawSh7diDt3tXtYh/d4yce23IYm7wq7RddpIl5ujEUm1FcGMcqe/5sPpZmoG978Tp XqvMccszZcz4XCFMSWE347gM4JX4Qo1saWOAEvH+eD4xYbA7n/fyUj1KzEVIwtId32Is J+MCvcRsfEPavmGBN8ZqZWp1QU6HgltcZB2Q5CTE/W+LO1FURNrDzxJZd9Cr/ubvHi0O XyRF+fdzus/GdHXrFOdqg2axx3UevGeL7Ib/WecEtUGAhewS+/vSV2QVRE3wlVYMgkWv Pu6w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=rdgw7TyQUZNkioPCfoavq9iEvsNCaU/l7xc9YjXyer4=; fh=2ZRqeRj+tJGBZXI5/vuEgwCJICMaGnNSISuCIUN+wQk=; b=Oze6r+NjLaX1Y3ppsRD48aUdsp2Ois0DZOxQ3blGtbwxlkmMkkop5ZxjRhaFj/QqT5 0t9+Me4wLzXfEwA6qlMMGk8CsL+3/lqZ3asMLQFTtyqpeJQgRRA8bnIHluiLO+sdZzwP g9Y4X6ILo+J1+ulVsPPWTfYtpE6vLJXEYT3Zsx4tVytNUGbAsSM4gCE7GO3Dxfl4HgOi nCKeq8oZzG+IBKA/H6igX79uyGj3iBHvBiTfWIuuLYpp5Xcps/Q/3UTTn64Qs9LhtTMt d3akn+P6U9awv4wcWgH5Y8uzsb9VNDvpRxBbw56E5jZudlPwtKoSdXiilV/it1JlFycF 0gxQ==; darn=lists.postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1780936566; x=1781541366; darn=lists.postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=rdgw7TyQUZNkioPCfoavq9iEvsNCaU/l7xc9YjXyer4=; b=K25XeHS2ZvWshCNWAuhJPDh3dSVe9x4xBhgF2VvEUQr5KEn4w6nAt7y8OZTcklUifU XXGQUFLvtVHd73zaAauOpr+x6GAoA3A0oYSi54DbZiT4jyiyOZB+U39IHPy0duYkqmlh Yu3hHQzQpVCCMtoyoHFnNm1cb9hRvT5eLGCJoB9eFKJus0vc77fQ2fffsoLXrNyy/Tzx acunPoYoAF9qSdkV5YcsHNnQQisH5MMrrQ2KZsyw/1XyB7//Y+J/J2ovcAlSZbwPzpTY 7rBQyDc8igQut+R7H02SY3Wp+aYfHkmvz9OR0V6FIaeze7bxnhkxXCeOZX3CoJNubIXC XLfg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780936566; x=1781541366; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=rdgw7TyQUZNkioPCfoavq9iEvsNCaU/l7xc9YjXyer4=; b=eq3JmO1/oRtoWtOzCo21moiHl0Uojew3MHpibk2Vft8upzwZ76RIfR+u+Imm8K1x4G ARVWbEHYJMaD1OddBJ5tTkU1CTGfxtsBaI99woDLKHB/ZSbWRtpabIMsXiqxKkIfUqcK kMA51LrguFNiphOssD1mV2rFtpo+vtlkBUFl2fOSXviIZaBI2gnMrFyRa1wbiXrwOS+B ZXMXZXDg2oppyjs9jthSyaBcYFFFA1qioA6dyMoBbZOqv5FzWOaYOnaDB23PNw2AY33G A6OzPtykjwPxqlmBO93sYlBpFYGgkSA/Vw6iGMndI4+0RTXKqlHg4YdWxY6bx94iKsbw YrlQ== X-Forwarded-Encrypted: i=1; AFNElJ+mobDFZbJKcBU/gM8a3GU8+tRGOC+7lyHg/Jes4IkpNIjC3s1ERSnVSWyDBios7Rbly7eMzG7sp40ElY8q@lists.postgresql.org X-Gm-Message-State: AOJu0YzElUrpurlKpADe5rmxoBKGX3LmJ0mNdR52CVef4MWbR2vDFk3B /usKnnO+C3dkmIRQN1rT/WR2tZqYz2nZn4vFhD6HEg3RLOrDKEZL4LuNl2ClNVZ+ZJ+30vEi2KS 7QPWgwpr9JFUvcCZoQWsmcZ4ra8chrJY= X-Gm-Gg: Acq92OH4WbvySBwtVEtYJ1aPwubLnqiaBimVYNs8f72Jit4OVnV6DH5uszhqPtR4+UX HGBZyhuDnV0xedB2EqP2w1NBqb8SN1IR+3KJ81GcWAZn0i4tn83RdlYx8GTOUJbAarXULLFGq2C G/eZZytRgF+QzzwT0efeUBncQnL/kjc0E2Y2940BH6NgwCayqZtduTYzY+xilVVNhyY6OK4xsq0 3LXkrYmqUinFUZ8fAQD0UoxVGwrb0XMWUrSvJRU8FSEa0tfQOklWAXirz8jPyy86vmkV+tOINR3 rEGcY6iKYizSt24v2pZmWtQ184gGdE6Sbxe9oGerqmxGdpwW X-Received: by 2002:a17:906:8a42:b0:beb:a412:4597 with SMTP id a640c23a62f3a-bf370a66a14mr553600666b.16.1780936565316; Mon, 08 Jun 2026 09:36:05 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Sami Imseih Date: Mon, 8 Jun 2026 11:35:53 -0500 X-Gm-Features: AVVi8CcPije7InclW5H9iNJUGB-DDpjIn55I8O81nIOYubgXnhGskuXV0sxtLIU Message-ID: Subject: Re: Report oldest xmin source when autovacuum cannot remove tuples To: Shinya Kato Cc: Japin Li , wenhui qiu , PostgreSQL Hackers Content-Type: text/plain; charset="UTF-8" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk >> Additionally, I forgot to update meson.build, which caused the tests >> to fail. I have fixed that in the attached patch. > Oops, I made a slight mistake. Fixed. Thanks for the updated patch! I agree there is value in logging this information during vacuum/autovacuum, as unlike a view, it provides the ability to investigate historically what was blocking vacuum. Having both the vacuum logging and the view seems like a good combination to me. In terms of v5, I have some comments: 1/ Reporting the GID of a prepared transaction. This seems unnecessary. The logged xid is sufficient since a DBA can look up the GID via pg_prepared_xacts using the "transaction" column. I think we can remove GetPreparedTransactionGid() and just report the xid. 2/ Reporting the application_name of the standby. This could be valuable assuming the user sets application_name in the primary_conninfo string to make the standby distinguishable. The documentation [1] says this "should be set" for physical standbys, and in practice most deployments do so since synchronous_standby_names matches on it. However, instead of GetStandbyAppname(), can we use pgstat_get_beentry_by_proc_number() to get the application name and set it in dst->name while holding the shared ProcArrayLock? This is safe if we call pgstat_fetch_stat_numbackends() beforehand to prime the local backend status cache. The subsequent lookup is just a bsearch on local memory, so it adds negligible time under the lock. 3/ Over-allocation in GetXidHorizonBlockers(). + /* + * Allocate enough space for every PGPROC plus all replication slots. This + * is a generous upper bound (typically only 0-2 entries are returned), + * but keeps the logic simple for a diagnostic function that runs + * infrequently. + */ + max_blockers = arrayP->maxProcs + max_replication_slots; + result = palloc0_array(XidHorizonBlocker, max_blockers); This looks wasteful, especially with large max_connections. In practice only 1-3 entries are returned. Can we start with a small allocation (say 8) and repalloc when needed? 4/ Simplify the loop body by removing candidate_* temporaries. The values we set in dst don't need to be tracked in separate variables. If dst gets populated for the proc, we can just do: ``` if (dst) { dst->pid = proc->pid; dst->xid = horizon; dst->proc_number = pgprocno; } ``` at the end of each iteration. 5/ GetXidHorizonBlocker() priority scan. +/* + * Get the highest-priority blocker holding back the xid horizon. + * + * Returns true and stores the blocker in *blocker if any are found. + */ The priority scan makes sense and addresses the concern I raised earlier [2] about reporting the wrong blocker due to ProcArray ordering. Without it we report whichever blocker happens to come first in ProcArray order. If an xmin-holder sits at a lower index than the xid-holder, we would report the less actionable one. The xid-holder is more useful to surface because killing that single transaction advances the horizon, whereas xmin-holders only matter once all of them release. One small optimization: exit the loop early once we find an xid-match type, since nothing can beat it: for (int i = 0; i < nblockers; i++) { if (best == NULL || blockers[i].type < best->type) { best = &blockers[i]; /* xid-match types can't be beaten, stop early */ if (best->type <= XHB_PREPARED_TRANSACTION) break; } } Finally, the infrastructure added here (GetXidHorizonBlockers, XidHorizonBlocker struct, the enum-based priority) will also underpin the future SQL-callable view for real-time blocker reporting, so I think what is being done here is good for that case also. I would also think that GetXidHorizonBlockers() and friends should be a separate patch, and the vacuum logging and future SQL view work can build off of it. [1] https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-PRIMARY-CONNINFO [2] https://www.postgresql.org/message-id/CAA5RZ0sjMgMo4Xg-niyyF-CpkQ_CK6uOfNKYT%3D9RmiBkAxQkbQ%40mail.gmail.com -- Sami Imseih Amazon Web Services (AWS)