8000 Avoid useless respawining the autovacuum launcher at high speed. · hackingwu/postgres@aeaaf62 · GitHub
[go: up one dir, main page]

Skip to content

Commit aeaaf62

Browse files
committed
Avoid useless respawining the autovacuum launcher at high speed.
When (1) autovacuum = off and (2) there's at least one database with an XID age greater than autovacuum_freeze_max_age and (3) all tables in that database that need vacuuming are already being processed by a worker and (4) the autovacuum launcher is started, a kind of infinite loop occurs. The launcher starts a worker and immediately exits. The worker, finding no worker to do, immediately starts the launcher, supposedly so that the next database can be processed. But because datfrozenxid for that database hasn't been advanced yet, the new worker gets put right back into the same database as the old one, where it once again starts the launcher and exits. High-speed ping pong ensues. There are several possible ways to break the cycle; this seems like the safest one. Amit Khandekar (code) and Robert Haas (comments), reviewed by Álvaro Herrera. Discussion: http://postgr.es/m/CAJ3gD9eWejf72HKquKSzax0r+epS=nAbQKNnykkMA0E8c+rMDg@mail.gmail.com
1 parent b60f982 commit aeaaf62

File tree

1 file changed

+23
-1
lines changed

1 file changed

+23
-1
lines changed

src/backend/postmaster/autovacuum.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1899,6 +1899,8 @@ do_autovacuum(void)
18991899
ScanKeyData key;
19001900
TupleDesc pg_class_desc;
19011901
int effective_multixact_freeze_max_age;
1902+
bool did_vacuum = false;
1903+
bool found_concurrent_worker = false;
19021904

19031905
/*
19041906
* StartTransactionCommand and CommitTransactionCommand will automatically
@@ -2241,6 +2243,7 @@ do_autovacuum(void)
22412243
if (worker->wi_tableoid == relid)
22422244
{
22432245
skipit = true;
2246+
found_concurrent_worker = true;
22442247
break;
22452248
}
22462249
}
@@ -2367,6 +2370,8 @@ do_autovacuum(void)
23672370
}
23682371
PG_END_TRY();
23692372

2373+
did_vacuum = true;
2374+
23702375
/* the PGXACT flags are reset at the next end of transaction */
23712376

23722377
/* be tidy */
@@ -2404,8 +2409,25 @@ do_autovacuum(void)
24042409
/*
24052410
* Update pg_database.datfrozenxid, and truncate pg_clog if possible. We
24062411
* only need to do this once, not after each table.
2412+
*
2413+
* Even if we didn't vacuum anything, it may still be important to do
2414+
* this, because one indirect effect of vac_update_datfrozenxid() is to
2415+
* update ShmemVariableCache->xidVacLimit. That might need to be done
2416+
* even if we haven't vacuumed anything, because relations with older
2417+
* relfrozenxid values or other databases with older datfrozenxid values
2418+
* might have been dropped, allowing xidVacLimit to advance.
2419+
*
2420+
* However, it's also important not to do this blindly in all cases,
2421+
* because when autovacuum=off this will restart the autovacuum launcher.
2422+
* If we're not careful, an infinite loop can result, where workers find
2423+
* no work to do and restart the launcher, which starts another worker in
2424+
* the same database that finds no work to do. To prevent that, we skip
2425+
* this if (1) we found no work to do and (2) we skipped at least one
2426+
* table due to concurrent autovacuum activity. In that case, the other
2427+
* worker has already done it, or will do so when it finishes.
24072428
*/
2408-
vac_update_datfrozenxid();
2429+
if (did_vacuum || !found_concurrent_worker)
2430+
vac_update_datfrozenxid();
24092431

24102432
/* Finally close out the last transaction. */
24112433
CommitTransactionCommand();

0 commit comments

Comments
 (0)
0