Add a developer-GUC 'gloabl_snapshot_source' to allow informed users to
authorPavan Deolasee <[email protected]>
Thu, 10 Dec 2015 05:44:23 +0000 (11:14 +0530)
committerPavan Deolasee <[email protected]>
Thu, 10 Dec 2015 05:44:23 +0000 (11:14 +0530)
override the way snapshots are computed.

The default value of the GUC is 'gtm' which means that snapshots are always
generated on the GTM so that we get a full and correct view of the currently
running transactions. But with this developer-GUC we now allow users to
override that and work with a coordinator generated snapshots. This can be
especially useful for read-only queries which now don't need to talk to the
GTM. If the snapshots can also be taken locally on a coordinator, this will
even further reduce the round-trips to the GTM. Of course, this can lead to
consistency issues because a coordinator may not be aware of all the
transactions currently running on the XL cluster, especially in a
multi-coordinator setup where different coordinators could be running different
transactions without knowing about each other's activity. But even in a single
coordinator setup, some transactions may start on a datanode and coordinator
may not know about them or may only know quite late.

Its advised that this feature must be used with caution and after due
consideration of the effects

src/backend/storage/ipc/procarray.c
src/backend/utils/misc/guc.c
src/include/storage/procarray.h

index 1407bfc07d55faa9494688a9c13a7d593e86581b..d344c68e4cd247d3280abf30614fe7ffde4a5abb 100644 (file)
@@ -79,6 +79,7 @@
 #include "pgxc/pgxc.h"
 #include "access/gtm.h"
 #include "storage/ipc.h"
+#include "utils/guc.h"
 /* PGXC_DATANODE */
 #include "postmaster/autovacuum.h"
 #endif
@@ -219,6 +220,10 @@ static TransactionId KnownAssignedXidsGetOldestXmin(void);
 static void KnownAssignedXidsDisplay(int trace_level);
 static void KnownAssignedXidsReset(void);
 
+#ifdef XCP
+int    GlobalSnapshotSource;
+#endif
+
 /*
  * Report shared-memory space needed by CreateSharedProcArray.
  */
@@ -1508,22 +1513,35 @@ GetSnapshotData(Snapshot snapshot)
 
 #ifdef PGXC  /* PGXC_DATANODE */
        /*
-        * Obtain a global snapshot for a Postgres-XC session
-        * if possible.
-        */
-       if (GetPGXCSnapshotData(snapshot))
-               return snapshot;
-       /*
-        * We only make one exception for using local snapshot and that's the
-        * initdb time. When IsPostmasterEnvironment is true, snapshots must either
-        * be pushed down from the coordinator or directly obtained from the
-        * GTM.
-        *
-        * !!TODO We don't seem to fully support Hot Standby. So why should we even
-        * exempt RecoveryInProgress()?
-        */
-       if (IsPostmasterEnvironment && !useLocalXid)
-               elog(ERROR, "Was unable to obtain a snapshot from GTM.");
+        * If the user has chosen to work with a coordinator-local snapshot, just
+        * compute snapshot locally. This can have adverse effects on the global
+        * consistency, in a multi-coordinator environment, but also in a
+        * single-coordinator setup because our recent changes to transaction
+        * management now allows datanodes to start global snapshots or more
+        * precisely attach current transaction to a global transaction. But users
+        * may still want to use this model for performance of their XL cluster, at
+        * the cost of reduced global consistency
+        */ 
+       if (GlobalSnapshotSource == GLOBAL_SNAPSHOT_SOURCE_GTM)
+       {
+               /*
+                * Obtain a global snapshot for a Postgres-XC session
+                * if possible.
+                */
+               if (GetPGXCSnapshotData(snapshot))
+                       return snapshot;
+               /*
+                * We only make one exception for using local snapshot and that's the
+                * initdb time. When IsPostmasterEnvironment is true, snapshots must
+                * either be pushed down from the coordinator or directly obtained from
+                * the GTM.
+                *
+                * !!TODO We don't seem to fully support Hot Standby. So why should we
+                * even exempt RecoveryInProgress()?
+                */
+               if (IsPostmasterEnvironment && !useLocalXid)
+                       elog(ERROR, "Was unable to obtain a snapshot from GTM.");
+       }
 #endif
 
        /*
@@ -3254,8 +3272,6 @@ GetSnapshotFromGlobalSnapshot(Snapshot snapshot)
                                globalSnapshot.snapshot_source == SNAPSHOT_DIRECT)
                                && TransactionIdIsValid(globalSnapshot.gxmin))
        {
-               int index;
-               ProcArrayStruct *arrayP = procArray;
                TransactionId global_xmin;
 
                snapshot->xmin = globalSnapshot.gxmin;
@@ -4360,7 +4376,6 @@ ProcArrayCheckXminConsistency(TransactionId global_xmin)
        for (index = 0; index < arrayP->numProcs; index++)
        {
                int                     pgprocno = arrayP->pgprocnos[index];
-               volatile PGPROC *proc = &allProcs[pgprocno];
                volatile PGXACT *pgxact = &allPgXact[pgprocno];
                TransactionId xid;
 
index ae251089cc495cb230daf8b450f709409b70812f..bf80a0ed60af59d9a57944b5aaa7802dbbdb464e 100644 (file)
 #include "pgxc/poolmgr.h"
 #include "pgxc/nodemgr.h"
 #include "pgxc/xc_maintenance_mode.h"
+#include "storage/procarray.h"
 #endif
 #ifdef XCP
 #include "commands/sequence.h"
+#include "parser/parse_utilcmd.h"
 #include "pgxc/nodemgr.h"
 #include "pgxc/squeue.h"
 #include "utils/snapmgr.h"
-#include "parser/parse_utilcmd.h"
 #endif
 #include "postmaster/autovacuum.h"
 #include "postmaster/bgworker.h"
@@ -445,6 +446,18 @@ static const struct config_enum_entry row_security_options[] = {
        {NULL, 0, false}
 };
 
+#ifdef XCP
+/*
+ * Set global-snapshot source. 'gtm' is default, but user can choose
+ * 'coordinator' for performance improvement at the cost of reduced consistency
+ */
+static const struct config_enum_entry global_snapshot_source_options[] = {
+       {"gtm", GLOBAL_SNAPSHOT_SOURCE_GTM, true},
+       {"coordinator", GLOBAL_SNAPSHOT_SOURCE_COORDINATOR, true},
+       {NULL, 0, false}
+};
+#endif
+
 /*
  * Options for enum values stored in other modules
  */
@@ -4051,6 +4064,20 @@ static struct config_enum ConfigureNamesEnum[] =
                NULL, NULL, NULL
        },
 
+#ifdef XCP
+       {
+               {"global_snapshot_source", PGC_USERSET, DEVELOPER_OPTIONS,
+                       gettext_noop("Set preferred source of a snapshot."),
+                       gettext_noop("When set to 'coordinator', a snapshot is taken at "
+                                       "the coordinator at the risk of reduced consistency. "
+                                       "Default is 'gtm'")
+               },
+               &GlobalSnapshotSource,
+               GLOBAL_SNAPSHOT_SOURCE_GTM, global_snapshot_source_options,
+               NULL, NULL, NULL
+       },
+#endif
+
        /* End-of-list marker */
        {
                {NULL, 0, 0, NULL, NULL}, NULL, 0, NULL, NULL, NULL, NULL
index f17fc22e65b5095bc58441f9389109e2f9320640..2ddad067fcc4bce18439345291ba0521f14b3df4 100644 (file)
 #include "utils/relcache.h"
 #include "utils/snapshot.h"
 
+#ifdef XCP
+extern int GlobalSnapshotSource;
+
+typedef enum GlobalSnapshotSourceType
+{
+       GLOBAL_SNAPSHOT_SOURCE_GTM,
+       GLOBAL_SNAPSHOT_SOURCE_COORDINATOR
+} GlobalSnapshotSourceType;
+#endif
 
 extern Size ProcArrayShmemSize(void);
 extern void CreateSharedProcArray(void);