WIP-horizon-stuff.diff
text/x-diff
Filename: WIP-horizon-stuff.diff
Type: text/x-diff
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| contrib/pg_surgery/expected/heap_surgery.out | 6 | 0 |
| contrib/pg_surgery/Makefile | 1 | 1 |
| contrib/pg_surgery/sql/heap_surgery.sql | 2 | 0 |
| src/backend/commands/vacuum.c | 0 | 16 |
| src/backend/storage/ipc/procarray.c | 40 | 1 |
diff --git i/src/backend/commands/vacuum.c w/src/backend/commands/vacuum.c
index ddeec870d81..8851fafed64 100644
--- i/src/backend/commands/vacuum.c
+++ w/src/backend/commands/vacuum.c
@@ -950,24 +950,8 @@ vacuum_set_xid_limits(Relation rel,
MultiXactId mxactLimit;
MultiXactId safeMxactLimit;
- if (RELATION_IS_LOCAL(rel) && !IsInTransactionBlock(isTopLevel))
{
/*
- * If we are processing a temp relation (which by prior checks must be
- * one belonging to our session), and we are not inside any
- * transaction block, then there can be no tuples in the rel that are
- * still in-doubt, nor can there be any that are dead but possibly
- * still interesting to some snapshot our session holds. We don't
- * need to care whether other sessions could see such tuples, either.
- * So we can aggressively set the cutoff xmin to be the nextXid.
- */
- *oldestXmin = ReadNewTransactionId();
- }
- else
- {
- /*
- * Otherwise, calculate the cutoff xmin normally.
- *
* We can always ignore processes running lazy vacuum. This is
* because we use these values only for deciding which tuples we must
* keep in the tables. Since lazy vacuum doesn't write its XID
diff --git i/src/backend/storage/ipc/procarray.c w/src/backend/storage/ipc/procarray.c
index 07c5eeb7495..c3cfe34ffee 100644
--- i/src/backend/storage/ipc/procarray.c
+++ w/src/backend/storage/ipc/procarray.c
@@ -153,6 +153,8 @@ typedef struct ProcArrayStruct
* I.e. the difference to GlobalVisCatalogRels is that
* replication slot's catalog_xmin is not taken into account.
*
+ * 4) GlobalVisTempRels, XXXX
+ *
* GlobalVisTestFor(relation) returns the appropriate state
* for the relation.
*
@@ -234,6 +236,9 @@ typedef struct ComputeXidHorizonsResult
* defined tables.
*/
TransactionId data_oldest_nonremovable;
+
+ TransactionId temp_oldest_nonremovable;
+
} ComputeXidHorizonsResult;
@@ -257,12 +262,13 @@ static TransactionId standbySnapshotPendingXmin;
/*
* State for visibility checks on different types of relations. See struct
- * GlobalVisState for details. As shared, catalog, and user defined
+ * GlobalVisState for details. As shared, catalog, normal and temporary
* relations can have different horizons, one such state exists for each.
*/
static GlobalVisState GlobalVisSharedRels;
static GlobalVisState GlobalVisCatalogRels;
static GlobalVisState GlobalVisDataRels;
+static GlobalVisState GlobalVisTempRels;
/*
* This backend's RecentXmin at the last time the accurate xmin horizon was
@@ -1668,6 +1674,10 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
h->oldest_considered_running = initial;
h->shared_oldest_nonremovable = initial;
h->data_oldest_nonremovable = initial;
+ if (TransactionIdIsValid(MyProc->xid))
+ h->temp_oldest_nonremovable = MyProc->xid;
+ else
+ h->temp_oldest_nonremovable = initial;
}
/*
@@ -1760,6 +1770,7 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
TransactionIdOlder(h->shared_oldest_nonremovable, kaxmin);
h->data_oldest_nonremovable =
TransactionIdOlder(h->data_oldest_nonremovable, kaxmin);
+ /* temp relations cannot be accessed in recovery */
}
else
{
@@ -1785,6 +1796,7 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
h->data_oldest_nonremovable =
TransactionIdRetreatedBy(h->data_oldest_nonremovable,
vacuum_defer_cleanup_age);
+ /* defer doesn't apply to temp relations */
}
/*
@@ -1844,6 +1856,8 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
h->catalog_oldest_nonremovable));
Assert(TransactionIdPrecedesOrEquals(h->oldest_considered_running,
h->data_oldest_nonremovable));
+ Assert(TransactionIdPrecedesOrEquals(h->oldest_considered_running,
+ h->temp_oldest_nonremovable));
Assert(!TransactionIdIsValid(h->slot_xmin) ||
TransactionIdPrecedesOrEquals(h->oldest_considered_running,
h->slot_xmin));
@@ -1878,6 +1892,8 @@ GetOldestNonRemovableTransactionId(Relation rel)
return horizons.shared_oldest_nonremovable;
else if (RelationIsAccessibleInLogicalDecoding(rel))
return horizons.catalog_oldest_nonremovable;
+ else if (RELATION_IS_LOCAL(rel))
+ return horizons.temp_oldest_nonremovable;
else
return horizons.data_oldest_nonremovable;
}
@@ -2357,6 +2373,9 @@ GetSnapshotData(Snapshot snapshot)
GlobalVisDataRels.definitely_needed =
FullTransactionIdNewer(def_vis_fxid_data,
GlobalVisDataRels.definitely_needed);
+ GlobalVisTempRels.definitely_needed =
+ FullTransactionIdNewer(latest_completed,
+ GlobalVisTempRels.definitely_needed);
/*
* Check if we know that we can initialize or increase the lower
@@ -2375,6 +2394,18 @@ GetSnapshotData(Snapshot snapshot)
GlobalVisDataRels.maybe_needed =
FullTransactionIdNewer(GlobalVisDataRels.maybe_needed,
oldestfxid);
+ if (TransactionIdIsNormal(myxid))
+ {
+ GlobalVisTempRels.maybe_needed =
+ FullTransactionIdNewer(GlobalVisTempRels.maybe_needed,
+ FullXidRelativeTo(latest_completed, myxid));
+ }
+ else
+ {
+ GlobalVisTempRels.maybe_needed =
+ FullTransactionIdNewer(GlobalVisTempRels.maybe_needed,
+ latest_completed);
+ }
}
RecentXmin = xmin;
@@ -3892,6 +3923,8 @@ GlobalVisTestFor(Relation rel)
state = &GlobalVisSharedRels;
else if (need_catalog)
state = &GlobalVisCatalogRels;
+ else if (RELATION_IS_LOCAL(rel))
+ state = &GlobalVisTempRels;
else
state = &GlobalVisDataRels;
@@ -3942,6 +3975,9 @@ GlobalVisUpdateApply(ComputeXidHorizonsResult *horizons)
GlobalVisDataRels.maybe_needed =
FullXidRelativeTo(horizons->latest_completed,
horizons->data_oldest_nonremovable);
+ GlobalVisTempRels.maybe_needed =
+ FullXidRelativeTo(horizons->latest_completed,
+ horizons->temp_oldest_nonremovable);
/*
* In longer running transactions it's possible that transactions we
@@ -3957,6 +3993,9 @@ GlobalVisUpdateApply(ComputeXidHorizonsResult *horizons)
GlobalVisDataRels.definitely_needed =
FullTransactionIdNewer(GlobalVisDataRels.maybe_needed,
GlobalVisDataRels.definitely_needed);
+ GlobalVisTempRels.definitely_needed =
+ FullTransactionIdNewer(GlobalVisTempRels.maybe_needed,
+ GlobalVisTempRels.definitely_needed);
ComputeXidHorizonsResultLastXmin = RecentXmin;
}
diff --git i/contrib/pg_surgery/Makefile w/contrib/pg_surgery/Makefile
index a66776c4c41..48a96008cea 100644
--- i/contrib/pg_surgery/Makefile
+++ w/contrib/pg_surgery/Makefile
@@ -9,7 +9,7 @@ EXTENSION = pg_surgery
DATA = pg_surgery--1.0.sql
PGFILEDESC = "pg_surgery - perform surgery on a damaged relation"
-REGRESS = heap_surgery
+REGRESS = --schedule=$(srcdir)/surgery_schedule
ifdef USE_PGXS
PG_CONFIG = pg_config
diff --git i/contrib/pg_surgery/expected/heap_surgery.out w/contrib/pg_surgery/expected/heap_surgery.out
index d4a757ffa01..6ef5597e7cc 100644
--- i/contrib/pg_surgery/expected/heap_surgery.out
+++ w/contrib/pg_surgery/expected/heap_surgery.out
@@ -1,4 +1,10 @@
create extension pg_surgery;
+select pg_sleep(0.1); -- ensure concurrent transaction is ready
+ pg_sleep
+----------
+
+(1 row)
+
-- create a normal heap table and insert some rows.
-- use a temp table so that vacuum behavior doesn't depend on global xmin
create temp table htab (a int);
diff --git i/contrib/pg_surgery/sql/heap_surgery.sql w/contrib/pg_surgery/sql/heap_surgery.sql
index 6526b27535d..212c657f3c7 100644
--- i/contrib/pg_surgery/sql/heap_surgery.sql
+++ w/contrib/pg_surgery/sql/heap_surgery.sql
@@ -1,5 +1,7 @@
create extension pg_surgery;
+select pg_sleep(0.1); -- ensure concurrent transaction is ready
+
-- create a normal heap table and insert some rows.
-- use a temp table so that vacuum behavior doesn't depend on global xmin
create temp table htab (a int);