1
0
mirror of https://github.com/postgres/postgres.git synced 2025-10-19 15:49:24 +03:00

Test IsInTransactionChain, not IsTransactionBlock, in vac_update_relstats.

As noted by Noah Misch, my initial cut at fixing bug #11638 didn't cover
all cases where ANALYZE might be invoked in an unsafe context.  We need to
test the result of IsInTransactionChain not IsTransactionBlock; which is
notationally a pain because IsInTransactionChain requires an isTopLevel
flag, which would have to be passed down through several levels of callers.
I chose to pass in_outer_xact (ie, the result of IsInTransactionChain)
rather than isTopLevel per se, as that seemed marginally more apropos
for the intermediate functions to know about.
This commit is contained in:
Tom Lane
2014-10-30 13:03:22 -04:00
parent 6057c212f3
commit fd0f651a86
4 changed files with 31 additions and 20 deletions

View File

@@ -206,6 +206,8 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
*/
if (use_own_xacts)
{
Assert(!in_outer_xact);
/* ActiveSnapshot is not set by autovacuum */
if (ActiveSnapshotSet())
PopActiveSnapshot();
@@ -251,7 +253,7 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
PushActiveSnapshot(GetTransactionSnapshot());
}
analyze_rel(relid, vacstmt, vac_strategy);
analyze_rel(relid, vacstmt, in_outer_xact, vac_strategy);
if (use_own_xacts)
{
@@ -665,13 +667,13 @@ vac_estimate_reltuples(Relation relation, bool is_analyze,
* DDL flags such as relhasindex, by clearing them if no longer correct.
* It's safe to do this in VACUUM, which can't run in parallel with
* CREATE INDEX/RULE/TRIGGER and can't be part of a transaction block.
* However, it's *not* safe to do it in an ANALYZE that's within a
* transaction block, because for example the current transaction might
* However, it's *not* safe to do it in an ANALYZE that's within an
* outer transaction, because for example the current transaction might
* have dropped the last index; then we'd think relhasindex should be
* cleared, but if the transaction later rolls back this would be wrong.
* So we refrain from updating the DDL flags if we're inside a
* transaction block. This is OK since postponing the flag maintenance
* is always allowable.
* So we refrain from updating the DDL flags if we're inside an outer
* transaction. This is OK since postponing the flag maintenance is
* always allowable.
*
* This routine is shared by VACUUM and ANALYZE.
*/
@@ -680,7 +682,8 @@ vac_update_relstats(Relation relation,
BlockNumber num_pages, double num_tuples,
BlockNumber num_all_visible_pages,
bool hasindex, TransactionId frozenxid,
MultiXactId minmulti)
MultiXactId minmulti,
bool in_outer_xact)
{
Oid relid = RelationGetRelid(relation);
Relation rd;
@@ -716,9 +719,9 @@ vac_update_relstats(Relation relation,
dirty = true;
}
/* Apply DDL updates, but not inside a transaction block (see above) */
/* Apply DDL updates, but not inside an outer transaction (see above) */
if (!IsTransactionBlock())
if (!in_outer_xact)
{
/*
* If we didn't find any indexes, reset relhasindex.