diff options
-rw-r--r-- | src/backend/commands/vacuum.c | 41 | ||||
-rw-r--r-- | src/backend/commands/vacuumlazy.c | 20 | ||||
-rw-r--r-- | src/include/commands/vacuum.h | 4 |
3 files changed, 52 insertions, 13 deletions
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 478cf8253ff..dc481f30f5f 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -13,7 +13,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.299.4.4 2008/02/11 19:14:53 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.299.4.5 2009/11/10 18:01:26 alvherre Exp $ * *------------------------------------------------------------------------- */ @@ -176,10 +176,10 @@ static void vac_update_dbstats(Oid dbid, static void vac_truncate_clog(TransactionId vacuumXID, TransactionId frozenXID); static bool vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind); -static void full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt); +static bool full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt); static void scan_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages, VacPageList fraged_pages); -static void repair_frag(VRelStats *vacrelstats, Relation onerel, +static bool repair_frag(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages, VacPageList fraged_pages, int nindexes, Relation *Irel); static void move_chain_tuple(Relation rel, @@ -885,6 +885,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) bool result; AclId save_userid; bool save_secdefcxt; + bool heldoff; /* Begin a transaction for vacuuming this relation */ StartTransactionCommand(); @@ -1011,9 +1012,9 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) * Do the actual work --- either FULL or "lazy" vacuum */ if (vacstmt->full) - full_vacuum_rel(onerel, vacstmt); + heldoff = full_vacuum_rel(onerel, vacstmt); else - lazy_vacuum_rel(onerel, vacstmt); + heldoff = lazy_vacuum_rel(onerel, vacstmt); result = true; /* did the vacuum */ @@ -1029,6 +1030,10 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) StrategyHintVacuum(false); CommitTransactionCommand(); + /* now we can allow interrupts again, if disabled */ + if (heldoff) + RESUME_INTERRUPTS(); + /* * If the relation has a secondary toast rel, vacuum that too while we * still hold the session lock on the master table. Note however that @@ -1067,8 +1072,11 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) * * At entry, we have already established a transaction and opened * and locked the relation. + * + * The return value indicates whether this function has held off + * interrupts -- caller must RESUME_INTERRUPTS() after commit if true. */ -static void +static bool full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt) { VacPageListData vacuum_pages; /* List of pages to vacuum and/or @@ -1079,6 +1087,7 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt) int nindexes, i; VRelStats *vacrelstats; + bool heldoff = false; vacuum_set_xid_limits(vacstmt, onerel->rd_rel->relisshared, &OldestXmin, &FreezeLimit); @@ -1120,8 +1129,8 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt) if (fraged_pages.num_pages > 0) { /* Try to shrink heap */ - repair_frag(vacrelstats, onerel, &vacuum_pages, &fraged_pages, - nindexes, Irel); + heldoff = repair_frag(vacrelstats, onerel, &vacuum_pages, &fraged_pages, + nindexes, Irel); vac_close_indexes(nindexes, Irel, NoLock); } else @@ -1150,6 +1159,8 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt) /* update statistics in pg_class */ vac_update_relstats(RelationGetRelid(onerel), vacrelstats->rel_pages, vacrelstats->rel_tuples, vacrelstats->hasindex); + + return heldoff; } @@ -1563,8 +1574,11 @@ scan_heap(VRelStats *vacrelstats, Relation onerel, * for them after committing (in hack-manner - without losing locks * and freeing memory!) current transaction. It truncates relation * if some end-blocks are gone away. + * + * The return value indicates whether this function has held off + * interrupts -- caller must RESUME_INTERRUPTS() after commit if true. */ -static void +static bool repair_frag(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages, VacPageList fraged_pages, int nindexes, Relation *Irel) @@ -1588,6 +1602,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, vacuumed_pages; int keep_tuples = 0; VacRUsage ru0; + bool heldoff = false; vac_init_rusage(&ru0); @@ -2292,7 +2307,13 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, * a lot of extra code to close and re-open the relation, indexes, * etc. For now, a quick hack: record status of current * transaction as committed, and continue. + * + * We prevent cancel interrupts after this point to mitigate the + * problem that you can't abort the transaction now; caller is + * responsible for re-enabling them after committing the transaction. */ + HOLD_INTERRUPTS(); + heldoff = true; RecordTransactionCommit(); } @@ -2491,6 +2512,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, pfree(vacrelstats->vtlinks); ExecContext_Finish(&ec); + + return heldoff; } /* diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c index a7a9065f103..a7ce4b03ecd 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -33,7 +33,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.50.4.7 2009/01/06 14:56:03 heikki Exp $ + * $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.50.4.8 2009/11/10 18:01:27 alvherre Exp $ * *------------------------------------------------------------------------- */ @@ -135,8 +135,11 @@ static int vac_cmp_page_spaces(const void *left, const void *right); * * At entry, we have already established a transaction and opened * and locked the relation. + * + * The return value indicates whether this function has held off + * interrupts -- caller must RESUME_INTERRUPTS() after commit if true. */ -void +bool lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt) { LVRelStats *vacrelstats; @@ -144,6 +147,7 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt) int nindexes; bool hasindex; BlockNumber possibly_freeable; + bool heldoff = false; if (vacstmt->verbose) elevel = INFO; @@ -174,12 +178,22 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt) * * Don't even think about it unless we have a shot at releasing a goodly * number of pages. Otherwise, the time taken isn't worth it. + * + * Note that after we've truncated the heap, it's too late to abort the + * transaction; doing so would lose the sinval messages needed to tell the + * other backends about the table being shrunk. We prevent interrupts in + * that case; caller is responsible for re-enabling them after + * committing the transaction. */ possibly_freeable = vacrelstats->rel_pages - vacrelstats->nonempty_pages; if (possibly_freeable > 0 && (possibly_freeable >= REL_TRUNCATE_MINIMUM || possibly_freeable >= vacrelstats->rel_pages / REL_TRUNCATE_FRACTION)) + { + HOLD_INTERRUPTS(); + heldoff = true; lazy_truncate_heap(onerel, vacrelstats); + } /* Update shared free space map with final free space info */ lazy_update_fsm(onerel, vacrelstats); @@ -189,6 +203,8 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt) vacrelstats->rel_pages, vacrelstats->rel_tuples, hasindex); + + return heldoff; } diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h index 0434b6f5ec4..48e22523485 100644 --- a/src/include/commands/vacuum.h +++ b/src/include/commands/vacuum.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/commands/vacuum.h,v 1.59 2004/12/31 22:03:28 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/commands/vacuum.h,v 1.59.4.1 2009/11/10 18:01:27 alvherre Exp $ * *------------------------------------------------------------------------- */ @@ -142,7 +142,7 @@ extern const char *vac_show_rusage(VacRUsage *ru0); extern void vacuum_delay_point(void); /* in commands/vacuumlazy.c */ -extern void lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt); +extern bool lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt); /* in commands/analyze.c */ extern void analyze_rel(Oid relid, VacuumStmt *vacstmt); |