diff --git a/gpAux/gpdemo/demo_cluster.sh b/gpAux/gpdemo/demo_cluster.sh index 73a85ade494..f1a266cfdbb 100755 --- a/gpAux/gpdemo/demo_cluster.sh +++ b/gpAux/gpdemo/demo_cluster.sh @@ -347,6 +347,8 @@ if [ "${ENABLE_COPY}" == "true" ]; then ycmdb.yc_allow_copy_to_program=on ycmdb.yc_allow_copy_from_file=on ycmdb.yc_allow_copy_to_file=on + wal_level=hot_standby + hot_standby=on EOF fi diff --git a/gpcontrib/gpdebug/Makefile b/gpcontrib/gpdebug/Makefile new file mode 100644 index 00000000000..730c487b6cf --- /dev/null +++ b/gpcontrib/gpdebug/Makefile @@ -0,0 +1,12 @@ +# gpcontrib/gpdebug/Makefile + +MODULE_big = gpdebug +OBJS = gpdebug.o $(WIN32RES) + +EXTENSION = gpdebug +DATA = gpdebug--1.0.sql +PGFILEDESC = "gpdebug - An debug logging for PostgreSQL" + +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) diff --git a/gpcontrib/gpdebug/gpdebug--1.0.sql b/gpcontrib/gpdebug/gpdebug--1.0.sql new file mode 100644 index 00000000000..0a12fa1a07e --- /dev/null +++ b/gpcontrib/gpdebug/gpdebug--1.0.sql @@ -0,0 +1,2 @@ +CREATE OR REPLACE FUNCTION cleanupAllGangs() RETURNS BOOL +AS 'MODULE_PATHNAME','cleanupAllGangs' LANGUAGE C; diff --git a/gpcontrib/gpdebug/gpdebug.c b/gpcontrib/gpdebug/gpdebug.c new file mode 100644 index 00000000000..6708d2b9748 --- /dev/null +++ b/gpcontrib/gpdebug/gpdebug.c @@ -0,0 +1,27 @@ + + +/*------------------------------------------------------------------------------ + * gpdebug.c + * + * Copyright (c) 2014-2021, PostgreSQL Global Development Group + *------------------------------------------------------------------------------ + */ +#include "postgres.h" + + +#include "cdb/cdbvars.h" +#include "cdb/cdbgang.h" + +PG_MODULE_MAGIC; + +void _PG_init(void); + +PG_FUNCTION_INFO_V1(cleanupAllGangs); +Datum +cleanupAllGangs(PG_FUNCTION_ARGS) +{ + if (Gp_role != GP_ROLE_DISPATCH) + elog(ERROR, "cleanupAllGangs can only be executed on master"); + DisconnectAndDestroyAllGangs(false); + PG_RETURN_BOOL(true); +} \ No newline at end of file diff --git a/gpcontrib/gpdebug/gpdebug.control b/gpcontrib/gpdebug/gpdebug.control new file mode 100644 index 00000000000..3b53eeddd8c --- /dev/null +++ b/gpcontrib/gpdebug/gpdebug.control @@ -0,0 +1,5 @@ +# gpdebug extension +comment = 'provides debug functionality' +default_version = '1.0' +module_pathname = '$libdir/gpdebug' +relocatable = true diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index a0be6df4e2b..30272ae3ec1 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -1879,7 +1879,7 @@ GetOldestPreparedTransaction() void StandbyRecoverPreparedTransactions(bool overwriteOK) { - elog(ERROR, "Hot Standby not supported"); + // elog(ERROR, "Hot Standby not supported"); } /* diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index d963e3f76d0..30b15288abe 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -2329,8 +2329,8 @@ StartTransaction(void) * hot standby is enabled. This mode is not supported in * Greenplum yet. */ - AssertImply(DistributedTransactionContext != DTX_CONTEXT_LOCAL_ONLY, - !s->startedInRecovery); + // AssertImply(DistributedTransactionContext != DTX_CONTEXT_LOCAL_ONLY, + // !s->startedInRecovery); /* * MPP Modification * diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 8552d760b15..22930e74927 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -7200,7 +7200,7 @@ StartupXLOG(void) oldestActiveXID = PrescanPreparedTransactions(&xids, &nxids); else oldestActiveXID = checkPoint.oldestActiveXid; - Assert(TransactionIdIsValid(oldestActiveXID)); + // Assert(TransactionIdIsValid(oldestActiveXID)); /* Tell procarray about the range of xids it has to deal with */ ProcArrayInitRecovery(ShmemVariableCache->nextXid); diff --git a/src/backend/cdb/cdbutil.c b/src/backend/cdb/cdbutil.c index 0127f6d20d3..f39784bcd75 100644 --- a/src/backend/cdb/cdbutil.c +++ b/src/backend/cdb/cdbutil.c @@ -82,6 +82,7 @@ #endif bool gp_count_host_segments_using_address = false; +bool gp_dispatch_on_mirrors = false; MemoryContext CdbComponentsContext = NULL; static CdbComponentDatabases *cdb_component_dbs = NULL; @@ -92,6 +93,7 @@ static CdbComponentDatabases *getCdbComponentInfo(void); static void cleanupComponentIdleQEs(CdbComponentDatabaseInfo *cdi, bool includeWriter); static int CdbComponentDatabaseInfoCompare(const void *p1, const void *p2); +static int CdbComponentDatabaseInfoComparem(const void *p1, const void *p2); static GpSegConfigEntry * readGpSegConfigFromCatalog(int *total_dbs); static GpSegConfigEntry * readGpSegConfigFromFTSFiles(int *total_dbs); @@ -439,10 +441,20 @@ getCdbComponentInfo(void) pRow->numIdleQEs = 0; pRow->numActiveQEs = 0; - if (config->role != GP_SEGMENT_CONFIGURATION_ROLE_PRIMARY || - (gp_count_host_segments_using_address && - (config->hostip == NULL || strlen(config->hostip) == 0))) - continue; + if (gp_dispatch_on_mirrors) + { + if (config->role != GP_SEGMENT_CONFIGURATION_ROLE_MIRROR || + (gp_count_host_segments_using_address && + (config->hostip == NULL || strlen(config->hostip) == 0))) + continue; + } + else + { + if (config->role != GP_SEGMENT_CONFIGURATION_ROLE_PRIMARY || + (gp_count_host_segments_using_address && + (config->hostip == NULL || strlen(config->hostip) == 0))) + continue; + } hsEntry = (HostSegsEntry *) hash_search(hostSegsHash, gp_count_host_segments_using_address ? config->hostip : config->hostname, @@ -474,14 +486,26 @@ getCdbComponentInfo(void) /* * Now sort the data by segindex, isprimary desc */ - qsort(component_databases->segment_db_info, - component_databases->total_segment_dbs, sizeof(CdbComponentDatabaseInfo), - CdbComponentDatabaseInfoCompare); + if (gp_dispatch_on_mirrors) + { + qsort(component_databases->segment_db_info, + component_databases->total_segment_dbs, sizeof(CdbComponentDatabaseInfo), + CdbComponentDatabaseInfoComparem); - qsort(component_databases->entry_db_info, - component_databases->total_entry_dbs, sizeof(CdbComponentDatabaseInfo), - CdbComponentDatabaseInfoCompare); + qsort(component_databases->entry_db_info, + component_databases->total_entry_dbs, sizeof(CdbComponentDatabaseInfo), + CdbComponentDatabaseInfoComparem); + } + else + { + qsort(component_databases->segment_db_info, + component_databases->total_segment_dbs, sizeof(CdbComponentDatabaseInfo), + CdbComponentDatabaseInfoCompare); + qsort(component_databases->entry_db_info, + component_databases->total_entry_dbs, sizeof(CdbComponentDatabaseInfo), + CdbComponentDatabaseInfoCompare); + } /* * Now count the number of distinct segindexes. Since it's sorted, this is * easy. @@ -558,10 +582,20 @@ getCdbComponentInfo(void) { cdbInfo = &component_databases->segment_db_info[i]; - if (cdbInfo->config->role != GP_SEGMENT_CONFIGURATION_ROLE_PRIMARY || - (gp_count_host_segments_using_address && - (cdbInfo->config->hostip == NULL || strlen(cdbInfo->config->hostip) == 0))) - continue; + if (gp_dispatch_on_mirrors) + { + if (cdbInfo->config->role != GP_SEGMENT_CONFIGURATION_ROLE_MIRROR || + (gp_count_host_segments_using_address && + (cdbInfo->config->hostip == NULL || strlen(cdbInfo->config->hostip) == 0))) + continue; + } + else + { + if (cdbInfo->config->role != GP_SEGMENT_CONFIGURATION_ROLE_PRIMARY || + (gp_count_host_segments_using_address && + (cdbInfo->config->hostip == NULL || strlen(cdbInfo->config->hostip) == 0))) + continue; + } hsEntry = (HostSegsEntry *) hash_search(hostSegsHash, gp_count_host_segments_using_address ? cdbInfo->config->hostip : cdbInfo->config->hostname, @@ -575,10 +609,20 @@ getCdbComponentInfo(void) { cdbInfo = &component_databases->entry_db_info[i]; - if (cdbInfo->config->role != GP_SEGMENT_CONFIGURATION_ROLE_PRIMARY || - (gp_count_host_segments_using_address && - (cdbInfo->config->hostip == NULL || strlen(cdbInfo->config->hostip) == 0))) - continue; + if (gp_dispatch_on_mirrors) + { + if (cdbInfo->config->role != GP_SEGMENT_CONFIGURATION_ROLE_MIRROR || + (gp_count_host_segments_using_address && + (cdbInfo->config->hostip == NULL || strlen(cdbInfo->config->hostip) == 0))) + continue; + } + else + { + if (cdbInfo->config->role != GP_SEGMENT_CONFIGURATION_ROLE_PRIMARY || + (gp_count_host_segments_using_address && + (cdbInfo->config->hostip == NULL || strlen(cdbInfo->config->hostip) == 0))) + continue; + } hsEntry = (HostSegsEntry *) hash_search(hostSegsHash, gp_count_host_segments_using_address ? cdbInfo->config->hostip : cdbInfo->config->hostname, @@ -847,7 +891,9 @@ cdbcomponent_allocateIdleQE(int contentId, SegmentType segmentType) * 1. for entrydb, it's never be writer. * 2. for first QE, it must be a writer. */ + /*XXX: what if gp_dispatch_on_mirrors?*/ isWriter = contentId == -1 ? false: (cdbinfo->numIdleQEs == 0 && cdbinfo->numActiveQEs == 0); + segdbDesc = cdbconn_createSegmentDescriptor(cdbinfo, nextQEIdentifer(cdbinfo->cdbs), isWriter); } @@ -1041,11 +1087,20 @@ cdbcomponent_getComponentInfo(int contentId) Assert(cdbs->total_segment_dbs == cdbs->total_segments * 2); cdbInfo = &cdbs->segment_db_info[2 * contentId]; - if (!SEGMENT_IS_ACTIVE_PRIMARY(cdbInfo)) + if (gp_dispatch_on_mirrors) { - cdbInfo = &cdbs->segment_db_info[2 * contentId + 1]; + if (!SEGMENT_IS_ACTIVE_MIRROR(cdbInfo)) + { + cdbInfo = &cdbs->segment_db_info[2 * contentId + 1]; + } + } + else + { + if (!SEGMENT_IS_ACTIVE_PRIMARY(cdbInfo)) + { + cdbInfo = &cdbs->segment_db_info[2 * contentId + 1]; + } } - return cdbInfo; } @@ -1228,6 +1283,31 @@ CdbComponentDatabaseInfoCompare(const void *p1, const void *p2) return cmp; } +static int +CdbComponentDatabaseInfoComparem(const void *p1, const void *p2) +{ + const CdbComponentDatabaseInfo *obj1 = (CdbComponentDatabaseInfo *) p1; + const CdbComponentDatabaseInfo *obj2 = (CdbComponentDatabaseInfo *) p2; + + int cmp = obj1->config->segindex - obj2->config->segindex; + + if (cmp == 0) + { + int obj2cmp = 0; + int obj1cmp = 0; + + if (SEGMENT_IS_ACTIVE_MIRROR(obj2)) + obj2cmp = 1; + + if (SEGMENT_IS_ACTIVE_MIRROR(obj1)) + obj1cmp = 1; + + cmp = obj2cmp - obj1cmp; + } + + return cmp; +} + /* * Maintain a cache of names. * diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8fa73b6236f..a523fa7cf64 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -36,6 +36,7 @@ #include "access/twophase.h" #include "access/twophase_rmgr.h" #include "cdb/cdbvars.h" +#include "cdb/cdbutil.h" #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" @@ -837,7 +838,7 @@ LockAcquireExtended(const LOCKTAG *locktag, if (lockmethodid == DEFAULT_LOCKMETHOD && locktag->locktag_type != LOCKTAG_TRANSACTION) { - if (Gp_role == GP_ROLE_EXECUTE && !Gp_is_writer) + if (Gp_role == GP_ROLE_EXECUTE && !Gp_is_writer && !gp_dispatch_on_mirrors) { if (lockHolderProcPtr == NULL || lockHolderProcPtr == MyProc) { @@ -857,7 +858,7 @@ LockAcquireExtended(const LOCKTAG *locktag, lockHolderProcPtr = proc; } else - ereport(FATAL, + ereport(WARNING, (errcode(ERRCODE_GP_INTERCONNECTION_ERROR), errmsg(WRITER_IS_MISSING_MSG), errdetail("lock [%u,%u] %s %d. " diff --git a/src/backend/utils/misc/guc_gp.c b/src/backend/utils/misc/guc_gp.c index 1e85c1ff255..da02c8b5b37 100644 --- a/src/backend/utils/misc/guc_gp.c +++ b/src/backend/utils/misc/guc_gp.c @@ -3197,7 +3197,13 @@ struct config_bool ConfigureNamesBool_gp[] = &gp_use_fastanalyze, false, NULL, NULL }, - + { + {"gp_dispatch_on_mirrors", PGC_USERSET, RESOURCES, + }, + &gp_dispatch_on_mirrors, + false, NULL, NULL + }, + { {"stats_queue_level", PGC_SUSET, STATS_COLLECTOR, gettext_noop("Collects resource queue-level statistics on database activity."), diff --git a/src/include/cdb/cdbutil.h b/src/include/cdb/cdbutil.h index 17570586fdb..236a2b6c5ef 100644 --- a/src/include/cdb/cdbutil.h +++ b/src/include/cdb/cdbutil.h @@ -206,6 +206,7 @@ extern int16 contentid_get_dbid(int16 contentid, char role, bool getPreferredRol extern int numsegmentsFromQD; extern bool gp_count_host_segments_using_address; +extern bool gp_dispatch_on_mirrors; /* * Returns the number of segments diff --git a/src/include/utils/unsync_guc_name.h b/src/include/utils/unsync_guc_name.h index 45adb3a496f..5ecc02ad167 100644 --- a/src/include/utils/unsync_guc_name.h +++ b/src/include/utils/unsync_guc_name.h @@ -160,6 +160,7 @@ "gp_dispatch_keepalives_idle", "gp_dispatch_keepalives_interval", "gp_dispatch_keepalives_count", + "gp_dispatch_on_mirrors", "gp_distinct_grouping_sets_threshold", "gp_dtx_recovery_interval", "gp_dtx_recovery_prepared_period",