Skip to content

Commit 23616b4

Browse files
committed
ARGH!
Vacuum must not advance pg_database.datvacuumxid nor truncate CLOG unless it's processed *all* tables in the database. Vacuums run by unprivileged users don't count. (Beats head against nearest convenient wall...)
1 parent 3468ed5 commit 23616b4

File tree

1 file changed

+38
-18
lines changed

1 file changed

+38
-18
lines changed

src/backend/commands/vacuum.c

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*
1414
*
1515
* IDENTIFICATION
16-
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.240 2002/09/23 20:43:41 tgl Exp $
16+
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.241 2002/09/27 20:57:08 tgl Exp $
1717
*
1818
*-------------------------------------------------------------------------
1919
*/
@@ -105,9 +105,6 @@ static int elevel = -1;
105105
static TransactionId OldestXmin;
106106
static TransactionId FreezeLimit;
107107

108-
static TransactionId initialOldestXmin;
109-
static TransactionId initialFreezeLimit;
110-
111108

112109
/* non-export function prototypes */
113110
static List *getrels(const RangeVar *vacrel, const char *stmttype);
@@ -116,7 +113,7 @@ static void vac_update_dbstats(Oid dbid,
116113
TransactionId frozenXID);
117114
static void vac_truncate_clog(TransactionId vacuumXID,
118115
TransactionId frozenXID);
119-
static void vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind);
116+
static bool vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind);
120117
static void full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt);
121118
static void scan_heap(VRelStats *vacrelstats, Relation onerel,
122119
VacPageList vacuum_pages, VacPageList fraged_pages);
@@ -160,6 +157,9 @@ vacuum(VacuumStmt *vacstmt)
160157
{
161158
const char *stmttype = vacstmt->vacuum ? "VACUUM" : "ANALYZE";
162159
MemoryContext anl_context = NULL;
160+
TransactionId initialOldestXmin = InvalidTransactionId;
161+
TransactionId initialFreezeLimit = InvalidTransactionId;
162+
bool all_rels;
163163
List *vrl,
164164
*cur;
165165

@@ -215,6 +215,9 @@ vacuum(VacuumStmt *vacstmt)
215215
ALLOCSET_DEFAULT_INITSIZE,
216216
ALLOCSET_DEFAULT_MAXSIZE);
217217

218+
/* Assume we are processing everything unless one table is mentioned */
219+
all_rels = (vacstmt->relation == NULL);
220+
218221
/* Build list of relations to process (note this lives in vac_context) */
219222
vrl = getrels(vacstmt->relation, stmttype);
220223

@@ -248,7 +251,7 @@ vacuum(VacuumStmt *vacstmt)
248251
*/
249252
if (vacstmt->vacuum)
250253
{
251-
if (vacstmt->relation == NULL)
254+
if (all_rels)
252255
{
253256
/*
254257
* It's a database-wide VACUUM.
@@ -271,7 +274,8 @@ vacuum(VacuumStmt *vacstmt)
271274
* recorded in pg_database.
272275
*/
273276
vacuum_set_xid_limits(vacstmt, false,
274-
&initialOldestXmin, &initialFreezeLimit);
277+
&initialOldestXmin,
278+
&initialFreezeLimit);
275279
}
276280

277281
/* matches the StartTransaction in PostgresMain() */
@@ -286,7 +290,10 @@ vacuum(VacuumStmt *vacstmt)
286290
Oid relid = (Oid) lfirsti(cur);
287291

288292
if (vacstmt->vacuum)
289-
vacuum_rel(relid, vacstmt, RELKIND_RELATION);
293+
{
294+
if (! vacuum_rel(relid, vacstmt, RELKIND_RELATION))
295+
all_rels = false; /* forget about updating dbstats */
296+
}
290297
if (vacstmt->analyze)
291298
{
292299
MemoryContext old_context = NULL;
@@ -331,11 +338,11 @@ vacuum(VacuumStmt *vacstmt)
331338
StartTransactionCommand(true);
332339

333340
/*
334-
* If we did a database-wide VACUUM, update the database's
335-
* pg_database row with info about the transaction IDs used, and
336-
* try to truncate pg_clog.
341+
* If we completed a database-wide VACUUM without skipping any
342+
* relations, update the database's pg_database row with info
343+
* about the transaction IDs used, and try to truncate pg_clog.
337344
*/
338-
if (vacstmt->relation == NULL)
345+
if (all_rels)
339346
{
340347
vac_update_dbstats(MyDatabaseId,
341348
initialOldestXmin, initialFreezeLimit);
@@ -693,6 +700,11 @@ vac_truncate_clog(TransactionId vacuumXID, TransactionId frozenXID)
693700
/*
694701
* vacuum_rel() -- vacuum one heap relation
695702
*
703+
* Returns TRUE if we actually processed the relation (or can ignore it
704+
* for some reason), FALSE if we failed to process it due to permissions
705+
* or other reasons. (A FALSE result really means that some data
706+
* may have been left unvacuumed, so we can't update XID stats.)
707+
*
696708
* Doing one heap at a time incurs extra overhead, since we need to
697709
* check that the heap exists again just before we vacuum it. The
698710
* reason that we do this is so that vacuuming can be spread across
@@ -701,13 +713,14 @@ vac_truncate_clog(TransactionId vacuumXID, TransactionId frozenXID)
701713
*
702714
* At entry and exit, we are not inside a transaction.
703715
*/
704-
static void
716+
static bool
705717
vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
706718
{
707719
LOCKMODE lmode;
708720
Relation onerel;
709721
LockRelId onerelid;
710722
Oid toast_relid;
723+
bool result;
711724

712725
/* Begin a transaction for vacuuming this relation */
713726
StartTransactionCommand(true);
@@ -727,7 +740,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
727740
0, 0, 0))
728741
{
729742
CommitTransactionCommand(true);
730-
return;
743+
return true; /* okay 'cause no data there */
731744
}
732745

733746
/*
@@ -759,7 +772,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
759772
RelationGetRelationName(onerel));
760773
relation_close(onerel, lmode);
761774
CommitTransactionCommand(true);
762-
return;
775+
return false;
763776
}
764777

765778
/*
@@ -772,7 +785,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
772785
RelationGetRelationName(onerel));
773786
relation_close(onerel, lmode);
774787
CommitTransactionCommand(true);
775-
return;
788+
return false;
776789
}
777790

778791
/*
@@ -786,7 +799,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
786799
{
787800
relation_close(onerel, lmode);
788801
CommitTransactionCommand(true);
789-
return;
802+
return true; /* assume no long-lived data in temp tables */
790803
}
791804

792805
/*
@@ -815,6 +828,8 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
815828
else
816829
lazy_vacuum_rel(onerel, vacstmt);
817830

831+
result = true; /* did the vacuum */
832+
818833
/* all done with this class, but hold lock until commit */
819834
relation_close(onerel, NoLock);
820835

@@ -831,12 +846,17 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
831846
* statistics are totally unimportant for toast relations.
832847
*/
833848
if (toast_relid != InvalidOid)
834-
vacuum_rel(toast_relid, vacstmt, RELKIND_TOASTVALUE);
849+
{
850+
if (! vacuum_rel(toast_relid, vacstmt, RELKIND_TOASTVALUE))
851+
result = false; /* failed to vacuum the TOAST table? */
852+
}
835853

836854
/*
837855
* Now release the session-level lock on the master table.
838856
*/
839857
UnlockRelationForSession(&onerelid, lmode);
858+
859+
return result;
840860
}
841861

842862

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy