[HACKERS] Rethinking autovacuum.c memory handling

Поиск
Список
Период
Сортировка
От Tom Lane
Тема [HACKERS] Rethinking autovacuum.c memory handling
Дата
Msg-id 13849.1506114543@sss.pgh.pa.us
обсуждение исходный текст
Ответы Re: [HACKERS] Rethinking autovacuum.c memory handling  (Michael Paquier <michael.paquier@gmail.com>)
Re: [HACKERS] Rethinking autovacuum.c memory handling  (Alvaro Herrera <alvherre@alvh.no-ip.org>)
Список pgsql-hackers
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.

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.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);

              /*
--- 2444,2453 ----
           */
          PG_TRY();
          {
+             /* Use PortalContext for any per-table allocations */
+             MemoryContextSwitchTo(PortalContext);
+
              /* have at it */
              autovacuum_do_vac_analyze(tab, bstrategy);

              /*
*************** do_autovacuum(void)
*** 2482,2487 ****
--- 2484,2492 ----
          }
          PG_END_TRY();

+         /* Make sure we're back in AutovacMemCxt */
+         MemoryContextSwitchTo(AutovacMemCxt);
+
          did_vacuum = true;

          /* the PGXACT flags are reset at the next end of transaction */
*************** perform_work_item(AutoVacuumWorkItem *wo
*** 2614,2619 ****
--- 2619,2627 ----

      autovac_report_workitem(workitem, cur_nspname, cur_datname);

+     /* clean up memory before each work item */
+     MemoryContextResetAndDeleteChildren(PortalContext);
+
      /*
       * 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);

          switch (workitem->avw_type)
          {
              case AVW_BRINSummarizeRange:
--- 2630,2639 ----
       */
      PG_TRY();
      {
!         /* Use PortalContext for any per-work-item allocations */
!         MemoryContextSwitchTo(PortalContext);

+         /* have at it */
          switch (workitem->avw_type)
          {
              case AVW_BRINSummarizeRange:
*************** perform_work_item(AutoVacuumWorkItem *wo
*** 2668,2673 ****
--- 2677,2685 ----
      }
      PG_END_TRY();

+     /* Make sure we're back in AutovacMemCxt */
+     MemoryContextSwitchTo(AutovacMemCxt);
+
      /* We intentionally do not set did_vacuum here */

      /* be tidy */

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

В списке pgsql-hackers по дате отправления:

Предыдущее
От: Peter Eisentraut
Дата:
Сообщение: Re: [HACKERS] Rewriting the test of pg_upgrade as a TAP test
Следующее
От: Robert Haas
Дата:
Сообщение: Re: [HACKERS] [Proposal] Make the optimiser aware of partitions ordering