Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dvVCA-0005h9-TR for pgsql-hackers@arkaria.postgresql.org; Fri, 22 Sep 2017 21:09:11 +0000 Received: from localhost ([127.0.0.1] helo=postgresql.org) by malur.postgresql.org with smtp (Exim 4.84_2) (envelope-from ) id 1dvVC9-0001hx-M4 for pgsql-hackers@arkaria.postgresql.org; Fri, 22 Sep 2017 21:09:09 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1dvVC8-0001gw-JY for pgsql-hackers@postgreSQL.org; Fri, 22 Sep 2017 21:09:08 +0000 Received: from sss.pgh.pa.us ([66.207.139.130]) by magus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1dvVC5-0007IQ-OL for pgsql-hackers@postgreSQL.org; Fri, 22 Sep 2017 21:09:08 +0000 Received: from sss1.sss.pgh.pa.us (localhost [127.0.0.1]) by sss.pgh.pa.us (8.14.4/8.14.4) with ESMTP id v8ML93nF013850; Fri, 22 Sep 2017 17:09:03 -0400 From: Tom Lane To: Alvaro Herrera cc: pgsql-hackers@postgreSQL.org Subject: Rethinking autovacuum.c memory handling MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" Content-ID: <13729.1506114327.0@sss.pgh.pa.us> Date: Fri, 22 Sep 2017 17:09:03 -0400 Message-ID: <13849.1506114543@sss.pgh.pa.us> List-Archive: List-Help: List-ID: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: X-Mailing-List: pgsql-hackers Precedence: bulk Sender: pgsql-hackers-owner@postgresql.org ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="us-ascii" Content-ID: <13729.1506114327.1@sss.pgh.pa.us> I notice that autovacuum.c calls autovacuum_do_vac_analyze, and thereby vacuum(), in TopTransactionContext. This doesn't seem like a terribly great idea, because it doesn't correspond to what happens during a manually-invoked vacuum. TopTransactionContext will go away when vacuum() commits the outer transaction, whereas in non-autovac usage, we call vacuum() in a PortalHeapMemory context that is not a child of TopTransactionContext and is not at risk of being reset multiple times during the vacuum(). This'd be a hazard if autovacuum_do_vac_analyze or vacuum did any palloc's before getting to the main loop. More generally, I'm not aware of other cases where we invoke a function in a context that we know that function will destroy as it executes. I don't see any live bug associated with this in HEAD, but this behavior requires a rather ugly (and memory-leaking) workaround in the proposed patch to allow multiple vacuum target rels. What I think we should do instead is invoke autovacuum_do_vac_analyze in the PortalContext that do_autovacuum has created, which we already have a mechanism to reset once per table processed in do_autovacuum. The attached patch does that, and also modifies perform_work_item() to use the same approach. Right now perform_work_item() has a copied-and-pasted MemoryContextResetAndDeleteChildren(PortalContext) call in its error recovery path, but that seems a bit out of place given that perform_work_item() isn't using PortalContext otherwise. Comments, objections? regards, tom lane PS: I was disappointed to find out that perform_work_item() isn't exercised at all in the standard regression tests. ------- =_aaaaaaaaaa0 Content-Type: text/x-diff; name="use-portalcontext-in-autovacuum.patch"; charset="us-ascii" Content-ID: <13729.1506114327.2@sss.pgh.pa.us> Content-Description: use-portalcontext-in-autovacuum.patch Content-Transfer-Encoding: quoted-printable diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/a= utovacuum.c index b745d89..1a32433 100644 *** a/src/backend/postmaster/autovacuum.c --- b/src/backend/postmaster/autovacuum.c *************** do_autovacuum(void) *** 2444,2451 **** */ PG_TRY(); { /* have at it */ - MemoryContextSwitchTo(TopTransactionContext); autovacuum_do_vac_analyze(tab, bstrategy); =20=20 /* --- 2444,2453 ---- */ PG_TRY(); { + /* Use PortalContext for any per-table allocations */ + MemoryContextSwitchTo(PortalContext); +=20 /* have at it */ autovacuum_do_vac_analyze(tab, bstrategy); =20=20 /* *************** do_autovacuum(void) *** 2482,2487 **** --- 2484,2492 ---- } PG_END_TRY(); =20=20 + /* Make sure we're back in AutovacMemCxt */ + MemoryContextSwitchTo(AutovacMemCxt); +=20 did_vacuum =3D true; =20=20 /* the PGXACT flags are reset at the next end of transaction */ *************** perform_work_item(AutoVacuumWorkItem *wo *** 2614,2619 **** --- 2619,2627 ---- =20=20 autovac_report_workitem(workitem, cur_nspname, cur_datname); =20=20 + /* clean up memory before each work item */ + MemoryContextResetAndDeleteChildren(PortalContext); +=20 /* * We will abort the current work item if something errors out, and * continue with the next one; in particular, this happens if we are *************** perform_work_item(AutoVacuumWorkItem *wo *** 2622,2630 **** */ PG_TRY(); { ! /* have at it */ ! MemoryContextSwitchTo(TopTransactionContext); =20=20 switch (workitem->avw_type) { case AVW_BRINSummarizeRange: --- 2630,2639 ---- */ PG_TRY(); { ! /* Use PortalContext for any per-work-item allocations */ ! MemoryContextSwitchTo(PortalContext); =20=20 + /* have at it */ switch (workitem->avw_type) { case AVW_BRINSummarizeRange: *************** perform_work_item(AutoVacuumWorkItem *wo *** 2668,2673 **** --- 2677,2685 ---- } PG_END_TRY(); =20=20 + /* Make sure we're back in AutovacMemCxt */ + MemoryContextSwitchTo(AutovacMemCxt); +=20 /* We intentionally do not set did_vacuum here */ =20=20 /* be tidy */ ------- =_aaaaaaaaaa0 Content-Type: text/plain Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers ------- =_aaaaaaaaaa0--