Use own transactions while running ANALYZE
authorPavan Deolasee <[email protected]>
Fri, 7 Dec 2018 02:10:45 +0000 (07:40 +0530)
committerPavan Deolasee <[email protected]>
Fri, 7 Dec 2018 02:10:45 +0000 (07:40 +0530)
Commit c89ea7fe8d1686c78a31781449342ca2e056caea disabled running ANALYZE on
remote coordinators when done inside a transaction block. But per report from
Virendra Kumar, this has also affected ANALYZE outside transaction blocks
because the existing code was using own transactions only either for autovacuum
processes or when more than one tables are analyzed at the same time.

Work-around this by always using own transaction except when ANALYZE is
triggered by REFRESH MATERIALIZED VIEW, which doesn't like closing the current
transaction.

src/backend/commands/matview.c
src/backend/commands/vacuum.c
src/include/nodes/parsenodes.h

index 11d0ef9e11c9a461f379829e525cd6e1c425fb7f..8a629791cf9c8e10e3695ee4ea1c154aac1e4e40 100644 (file)
@@ -637,7 +637,7 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
                                get_namespace_name(RelationGetNamespace(tempRel)),
                                RelationGetRelationName(tempRel), -1);
                stmt->relation = rv;
-               stmt->options = VACOPT_ANALYZE;
+               stmt->options = VACOPT_ANALYZE | VACOPT_USE_OUTERXACT;
                ExecVacuum(stmt, true);
        }
 #endif
@@ -857,7 +857,7 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
                VacuumStmt *stmt = makeNode(VacuumStmt);
                RangeVar *rv = makeRangeVar(tempschema, diffname, -1);
                stmt->relation = rv;
-               stmt->options = VACOPT_ANALYZE;
+               stmt->options = VACOPT_ANALYZE | VACOPT_USE_OUTERXACT;
                ExecVacuum(stmt, true);
        }
 #endif
index bd62ae31add5a1965015d46a09268d2ec3e89795..2c89a8ac650a5518862ad4da20cd2ab0d74fb925 100644 (file)
@@ -256,10 +256,15 @@ vacuum(int options, RangeVar *relation, Oid relid, VacuumParams *params,
         * problematic.)
         *
         * For ANALYZE (no VACUUM): if inside a transaction block, we cannot
-        * start/commit our own transactions.  Also, there's no need to do so if
-        * only processing one relation.  For multiple relations when not within a
-        * transaction block, and also in an autovacuum worker, use own
+        * start/commit our own transactions. For multiple relations when not
+        * within a transaction block, and also in an autovacuum worker, use own
         * transactions so we can release locks sooner.
+        *
+        * XL: We use own transactions even for a single relation case since that
+        * allows us to safely analyze the remote coordinators too. We make
+        * exception while running implicit ANALYZE as part of REFRESH MATERIALIZED
+        * VIEW since that case demands that we must not close the current
+        * transaction.
         */
        if (options & VACOPT_VACUUM)
                use_own_xacts = true;
@@ -272,8 +277,11 @@ vacuum(int options, RangeVar *relation, Oid relid, VacuumParams *params,
                        use_own_xacts = false;
                else if (list_length(relations) > 1)
                        use_own_xacts = true;
-               else
+               else if (options & VACOPT_USE_OUTERXACT)
                        use_own_xacts = false;
+               else
+                       use_own_xacts = true;
+
        }
 
        /*
index 9baa210971209ab4038cdd4a34d77a9210651633..ab5d21b1ad3e9290c38d5c28ed559a5d7ab8a919 100644 (file)
@@ -3130,10 +3130,12 @@ typedef enum VacuumOption
        VACOPT_NOWAIT = 1 << 5,         /* don't wait to get lock (autovacuum only) */
        VACOPT_SKIPTOAST = 1 << 6,      /* don't process the TOAST table, if any */
        VACOPT_DISABLE_PAGE_SKIPPING = 1 << 7,  /* don't skip any pages */
-       VACOPT_COORDINATOR = 1 << 8     /* don't trigger analyze on the datanodes, but
+       VACOPT_COORDINATOR = 1 << 8,/* don't trigger analyze on the datanodes, but
                                                                 * just collect existing info and populate
                                                                 * coordinator side stats.
                                                                 */
+       /* do not use our own transactions */
+       VACOPT_USE_OUTERXACT = 1 << 9
 } VacuumOption;
 
 typedef struct VacuumStmt