Skip to content

Commit 4046e58

Browse files
committed
Initial implementation of concurrent VACUUM. Ifdef'd out for the moment,
because index locking issues are not handled correctly yet. Need to go work on the index AMs next.
1 parent 20ca834 commit 4046e58

File tree

4 files changed

+1090
-68
lines changed

4 files changed

+1090
-68
lines changed

src/backend/commands/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Makefile for commands
55
#
66
# IDENTIFICATION
7-
# $Header: /cvsroot/pgsql/src/backend/commands/Makefile,v 1.26 2000/08/31 16:09:53 petere Exp $
7+
# $Header: /cvsroot/pgsql/src/backend/commands/Makefile,v 1.27 2001/07/13 22:55:59 tgl Exp $
88
#
99
#-------------------------------------------------------------------------
1010

@@ -13,7 +13,7 @@ top_builddir = ../../..
1313
include $(top_builddir)/src/Makefile.global
1414

1515
OBJS = async.o creatinh.o command.o comment.o copy.o indexcmds.o define.o \
16-
remove.o rename.o vacuum.o analyze.o view.o cluster.o \
16+
remove.o rename.o vacuum.o vacuumlazy.o analyze.o view.o cluster.o \
1717
explain.o sequence.o trigger.o user.o proclang.o \
1818
dbcommands.o variable.o
1919

src/backend/commands/vacuum.c

Lines changed: 54 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,39 @@
11
/*-------------------------------------------------------------------------
22
*
33
* vacuum.c
4-
* the postgres vacuum cleaner
4+
* The postgres vacuum cleaner.
5+
*
6+
* This file includes the "full" version of VACUUM, as well as control code
7+
* used by all three of full VACUUM, lazy VACUUM, and ANALYZE. See
8+
* vacuumlazy.c and analyze.c for the rest of the code for the latter two.
9+
*
510
*
611
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
712
* Portions Copyright (c) 1994, Regents of the University of California
813
*
914
*
1015
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.203 2001/07/12 04:11:13 tgl Exp $
16+
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.204 2001/07/13 22:55:59 tgl Exp $
1217
*
1318
*-------------------------------------------------------------------------
1419
*/
1520
#include "postgres.h"
1621

17-
#include <fcntl.h>
1822
#include <unistd.h>
19-
#include <sys/types.h>
20-
#include <sys/file.h>
21-
#include <sys/stat.h>
2223

2324
#include "access/genam.h"
2425
#include "access/heapam.h"
2526
#include "access/xlog.h"
2627
#include "catalog/catalog.h"
2728
#include "catalog/catname.h"
28-
#include "catalog/index.h"
2929
#include "catalog/pg_index.h"
3030
#include "commands/vacuum.h"
3131
#include "executor/executor.h"
3232
#include "miscadmin.h"
33-
#include "nodes/execnodes.h"
3433
#include "storage/freespace.h"
3534
#include "storage/sinval.h"
3635
#include "storage/smgr.h"
3736
#include "tcop/pquery.h"
38-
#include "tcop/tcopprot.h"
3937
#include "utils/acl.h"
4038
#include "utils/builtins.h"
4139
#include "utils/fmgroids.h"
@@ -123,7 +121,7 @@ static void scan_heap(VRelStats *vacrelstats, Relation onerel,
123121
VacPageList vacuum_pages, VacPageList fraged_pages);
124122
static void repair_frag(VRelStats *vacrelstats, Relation onerel,
125123
VacPageList vacuum_pages, VacPageList fraged_pages,
126-
int nindices, Relation *Irel);
124+
int nindexes, Relation *Irel);
127125
static void vacuum_heap(VRelStats *vacrelstats, Relation onerel,
128126
VacPageList vacpagelist);
129127
static void vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage);
@@ -135,8 +133,6 @@ static void vac_update_fsm(Relation onerel, VacPageList fraged_pages,
135133
BlockNumber rel_pages);
136134
static VacPage copy_vac_page(VacPage vacpage);
137135
static void vpage_insert(VacPageList vacpagelist, VacPage vpnew);
138-
static void get_indices(Relation relation, int *nindices, Relation **Irel);
139-
static void close_indices(int nindices, Relation *Irel);
140136
static bool is_partial_index(Relation indrel);
141137
static void *vac_bsearch(const void *key, const void *base,
142138
size_t nelem, size_t size,
@@ -455,14 +451,6 @@ vac_update_relstats(Oid relid, BlockNumber num_pages, double num_tuples,
455451
*/
456452

457453

458-
/* XXX Temporary placeholder */
459-
static void
460-
lazy_vacuum_rel(Relation onerel)
461-
{
462-
full_vacuum_rel(onerel);
463-
}
464-
465-
466454
/*
467455
* vacuum_rel() -- vacuum one heap relation
468456
*
@@ -554,11 +542,17 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt)
554542

555543
/*
556544
* Do the actual work --- either FULL or "lazy" vacuum
545+
*
546+
* XXX for the moment, lazy vac not supported unless CONCURRENT_VACUUM
557547
*/
548+
#ifdef CONCURRENT_VACUUM
558549
if (vacstmt->full)
559550
full_vacuum_rel(onerel);
560551
else
561-
lazy_vacuum_rel(onerel);
552+
lazy_vacuum_rel(onerel, vacstmt);
553+
#else
554+
full_vacuum_rel(onerel);
555+
#endif
562556

563557
/* all done with this class, but hold lock until commit */
564558
heap_close(onerel, NoLock);
@@ -596,7 +590,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt)
596590
/*
597591
* full_vacuum_rel() -- perform FULL VACUUM for one heap relation
598592
*
599-
* This routine vacuums a single heap, cleans out its indices, and
593+
* This routine vacuums a single heap, cleans out its indexes, and
600594
* updates its num_pages and num_tuples statistics.
601595
*
602596
* At entry, we have already established a transaction and opened
@@ -606,11 +600,11 @@ static void
606600
full_vacuum_rel(Relation onerel)
607601
{
608602
VacPageListData vacuum_pages; /* List of pages to vacuum and/or
609-
* clean indices */
603+
* clean indexes */
610604
VacPageListData fraged_pages; /* List of pages with space enough
611605
* for re-using */
612606
Relation *Irel;
613-
int32 nindices,
607+
int nindexes,
614608
i;
615609
VRelStats *vacrelstats;
616610
bool reindex = false;
@@ -633,15 +627,13 @@ full_vacuum_rel(Relation onerel)
633627
vacuum_pages.num_pages = fraged_pages.num_pages = 0;
634628
scan_heap(vacrelstats, onerel, &vacuum_pages, &fraged_pages);
635629

636-
/* Now open all indices of the relation */
637-
nindices = 0;
638-
Irel = (Relation *) NULL;
639-
get_indices(onerel, &nindices, &Irel);
630+
/* Now open all indexes of the relation */
631+
vac_open_indexes(onerel, &nindexes, &Irel);
640632
if (!Irel)
641633
reindex = false;
642634
else if (!RelationGetForm(onerel)->relhasindex)
643635
reindex = true;
644-
if (nindices > 0)
636+
if (nindexes > 0)
645637
vacrelstats->hasindex = true;
646638

647639
#ifdef NOT_USED
@@ -651,7 +643,7 @@ full_vacuum_rel(Relation onerel)
651643
*/
652644
if (reindex)
653645
{
654-
close_indices(nindices, Irel);
646+
vac_close_indexes(nindexes, Irel);
655647
Irel = (Relation *) NULL;
656648
activate_indexes_of_a_table(RelationGetRelid(onerel), false);
657649
}
@@ -662,14 +654,14 @@ full_vacuum_rel(Relation onerel)
662654
{
663655
if (vacuum_pages.num_pages > 0)
664656
{
665-
for (i = 0; i < nindices; i++)
657+
for (i = 0; i < nindexes; i++)
666658
vacuum_index(&vacuum_pages, Irel[i],
667659
vacrelstats->rel_tuples, 0);
668660
}
669661
else
670662
{
671-
/* just scan indices to update statistic */
672-
for (i = 0; i < nindices; i++)
663+
/* just scan indexes to update statistic */
664+
for (i = 0; i < nindexes; i++)
673665
scan_index(Irel[i], vacrelstats->rel_tuples);
674666
}
675667
}
@@ -678,12 +670,12 @@ full_vacuum_rel(Relation onerel)
678670
{
679671
/* Try to shrink heap */
680672
repair_frag(vacrelstats, onerel, &vacuum_pages, &fraged_pages,
681-
nindices, Irel);
682-
close_indices(nindices, Irel);
673+
nindexes, Irel);
674+
vac_close_indexes(nindexes, Irel);
683675
}
684676
else
685677
{
686-
close_indices(nindices, Irel);
678+
vac_close_indexes(nindexes, Irel);
687679
if (vacuum_pages.num_pages > 0)
688680
{
689681
/* Clean pages from vacuum_pages list */
@@ -835,7 +827,7 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
835827
itemid = PageGetItemId(page, offnum);
836828

837829
/*
838-
* Collect un-used items too - it's possible to have indices
830+
* Collect un-used items too - it's possible to have indexes
839831
* pointing here after crash.
840832
*/
841833
if (!ItemIdIsUsed(itemid))
@@ -944,7 +936,7 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
944936
}
945937

946938
/* mark it unused on the temp page */
947-
lpp = &(((PageHeader) tempPage)->pd_linp[offnum - 1]);
939+
lpp = PageGetItemId(tempPage, offnum);
948940
lpp->lp_flags &= ~LP_USED;
949941

950942
vacpage->offsets[vacpage->offsets_free++] = offnum;
@@ -1073,16 +1065,16 @@ Re-using: Free/Avail. Space %.0f/%.0f; EndEmpty/Avail. Pages %u/%u. %s",
10731065
* repair_frag() -- try to repair relation's fragmentation
10741066
*
10751067
* This routine marks dead tuples as unused and tries re-use dead space
1076-
* by moving tuples (and inserting indices if needed). It constructs
1077-
* Nvacpagelist list of free-ed pages (moved tuples) and clean indices
1068+
* by moving tuples (and inserting indexes if needed). It constructs
1069+
* Nvacpagelist list of free-ed pages (moved tuples) and clean indexes
10781070
* for them after committing (in hack-manner - without losing locks
10791071
* and freeing memory!) current transaction. It truncates relation
10801072
* if some end-blocks are gone away.
10811073
*/
10821074
static void
10831075
repair_frag(VRelStats *vacrelstats, Relation onerel,
10841076
VacPageList vacuum_pages, VacPageList fraged_pages,
1085-
int nindices, Relation *Irel)
1077+
int nindexes, Relation *Irel)
10861078
{
10871079
TransactionId myXID;
10881080
CommandId myCID;
@@ -1884,7 +1876,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
18841876
* relation. Ideally we should do Commit/StartTransactionCommand
18851877
* here, relying on the session-level table lock to protect our
18861878
* exclusive access to the relation. However, that would require
1887-
* a lot of extra code to close and re-open the relation, indices,
1879+
* a lot of extra code to close and re-open the relation, indexes,
18881880
* etc. For now, a quick hack: record status of current
18891881
* transaction as committed, and continue.
18901882
*/
@@ -1985,7 +1977,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
19851977

19861978
if (Nvacpagelist.num_pages > 0)
19871979
{
1988-
/* vacuum indices again if needed */
1980+
/* vacuum indexes again if needed */
19891981
if (Irel != (Relation *) NULL)
19901982
{
19911983
VacPage *vpleft,
@@ -2002,7 +1994,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
20021994
*vpright = vpsave;
20031995
}
20041996
Assert(keep_tuples >= 0);
2005-
for (i = 0; i < nindices; i++)
1997+
for (i = 0; i < nindexes; i++)
20061998
vacuum_index(&Nvacpagelist, Irel[i],
20071999
vacrelstats->rel_tuples, keep_tuples);
20082000
}
@@ -2175,7 +2167,7 @@ vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage)
21752167
START_CRIT_SECTION();
21762168
for (i = 0; i < vacpage->offsets_free; i++)
21772169
{
2178-
itemid = &(((PageHeader) page)->pd_linp[vacpage->offsets[i] - 1]);
2170+
itemid = PageGetItemId(page, vacpage->offsets[i]);
21792171
itemid->lp_flags &= ~LP_USED;
21802172
}
21812173
uncnt = PageRepairFragmentation(page, unused);
@@ -2244,9 +2236,9 @@ scan_index(Relation indrel, double num_tuples)
22442236
*
22452237
* Vpl is the VacPageList of the heap we're currently vacuuming.
22462238
* It's locked. Indrel is an index relation on the vacuumed heap.
2247-
* We don't set locks on the index relation here, since the indexed
2248-
* access methods support locking at different granularities.
2249-
* We let them handle it.
2239+
*
2240+
* We don't bother to set locks on the index relation here, since
2241+
* the parent table is exclusive-locked already.
22502242
*
22512243
* Finally, we arrange to update the index relation's statistics in
22522244
* pg_class.
@@ -2555,19 +2547,19 @@ vac_cmp_vtlinks(const void *left, const void *right)
25552547
}
25562548

25572549

2558-
static void
2559-
get_indices(Relation relation, int *nindices, Relation **Irel)
2550+
void
2551+
vac_open_indexes(Relation relation, int *nindexes, Relation **Irel)
25602552
{
25612553
List *indexoidlist,
25622554
*indexoidscan;
25632555
int i;
25642556

25652557
indexoidlist = RelationGetIndexList(relation);
25662558

2567-
*nindices = length(indexoidlist);
2559+
*nindexes = length(indexoidlist);
25682560

2569-
if (*nindices > 0)
2570-
*Irel = (Relation *) palloc(*nindices * sizeof(Relation));
2561+
if (*nindexes > 0)
2562+
*Irel = (Relation *) palloc(*nindexes * sizeof(Relation));
25712563
else
25722564
*Irel = NULL;
25732565

@@ -2584,14 +2576,14 @@ get_indices(Relation relation, int *nindices, Relation **Irel)
25842576
}
25852577

25862578

2587-
static void
2588-
close_indices(int nindices, Relation *Irel)
2579+
void
2580+
vac_close_indexes(int nindexes, Relation *Irel)
25892581
{
25902582
if (Irel == (Relation *) NULL)
25912583
return;
25922584

2593-
while (nindices--)
2594-
index_close(Irel[nindices]);
2585+
while (nindexes--)
2586+
index_close(Irel[nindexes]);
25952587
pfree(Irel);
25962588
}
25972589

@@ -2621,22 +2613,20 @@ is_partial_index(Relation indrel)
26212613
static bool
26222614
enough_space(VacPage vacpage, Size len)
26232615
{
2624-
26252616
len = MAXALIGN(len);
26262617

26272618
if (len > vacpage->free)
26282619
return false;
26292620

2630-
if (vacpage->offsets_used < vacpage->offsets_free) /* there are free
2631-
* itemid(s) */
2632-
return true; /* and len <= free_space */
2621+
/* if there are free itemid(s) and len <= free_space... */
2622+
if (vacpage->offsets_used < vacpage->offsets_free)
2623+
return true;
26332624

2634-
/* ok. noff_usd >= noff_free and so we'll have to allocate new itemid */
2635-
if (len + MAXALIGN(sizeof(ItemIdData)) <= vacpage->free)
2625+
/* noff_used >= noff_free and so we'll have to allocate new itemid */
2626+
if (len + sizeof(ItemIdData) <= vacpage->free)
26362627
return true;
26372628

26382629
return false;
2639-
26402630
}
26412631

26422632

0 commit comments

Comments
 (0)