From 634fd0ade3bbe474e03db011e518731bc67ea3fc Mon Sep 17 00:00:00 2001 From: Zijie Date: Fri, 24 May 2024 10:43:45 +0800 Subject: [PATCH] Fix merge GPDB (GUC related) --- src/backend/cdb/cdbutil.c | 4 +- src/backend/cdb/dispatcher/cdbgang.c | 12 ++-- src/bin/gpfts/ftsprobe.c | 55 ++++++++++++++----- src/include/catalog/catversion.h | 2 +- src/include/catalog/pg_proc.dat | 2 +- .../isolation2/expected/fts_segment_reset.out | 3 +- .../regress/expected/gp_prepared_xacts.out | 2 +- src/test/regress/input/dispatch.source | 4 -- src/test/regress/output/dispatch.source | 22 -------- .../singlenode_regress/expected/memoize.out | 2 +- .../expected/query_finish_pending.out | 6 +- src/test/singlenode_regress/expected/temp.out | 22 ++++---- 12 files changed, 68 insertions(+), 68 deletions(-) diff --git a/src/backend/cdb/cdbutil.c b/src/backend/cdb/cdbutil.c index 152e04be6bb..5af92fb69f1 100644 --- a/src/backend/cdb/cdbutil.c +++ b/src/backend/cdb/cdbutil.c @@ -1965,7 +1965,7 @@ gp_get_suboverflowed_backends(PG_FUNCTION_ARGS) LWLockAcquire(ProcArrayLock, LW_SHARED); for (i = 0; i < ProcGlobal->allProcCount; i++) { - if (ProcGlobal->allPgXact[i].overflowed) + if (ProcGlobal->subxidStates[i].overflowed) astate = accumArrayResult(astate, Int32GetDatum(ProcGlobal->allProcs[i].pid), false, INT4OID, CurrentMemoryContext); @@ -4181,7 +4181,7 @@ gp_get_suboverflowed_backends(PG_FUNCTION_ARGS) LWLockAcquire(ProcArrayLock, LW_SHARED); for (i = 0; i < ProcGlobal->allProcCount; i++) { - if (ProcGlobal->allPgXact[i].overflowed) + if (ProcGlobal->subxidStates[i].overflowed) astate = accumArrayResult(astate, Int32GetDatum(ProcGlobal->allProcs[i].pid), false, INT4OID, CurrentMemoryContext); diff --git a/src/backend/cdb/dispatcher/cdbgang.c b/src/backend/cdb/dispatcher/cdbgang.c index f6149958b0c..f838ad5fadd 100644 --- a/src/backend/cdb/dispatcher/cdbgang.c +++ b/src/backend/cdb/dispatcher/cdbgang.c @@ -972,13 +972,13 @@ backend_type(SegmentDatabaseDescriptor *segdb) } /* - * qsort comparator for SegmentDatabaseDescriptors. Sorts by descriptor ID. + * sort comparator for SegmentDatabaseDescriptors. Sorts by descriptor ID. */ static int -compare_segdb_id(const void *v1, const void *v2) +compare_segdb_id(const ListCell *a, const ListCell *b) { - SegmentDatabaseDescriptor *d1 = (SegmentDatabaseDescriptor *) lfirst(*(ListCell **) v1); - SegmentDatabaseDescriptor *d2 = (SegmentDatabaseDescriptor *) lfirst(*(ListCell **) v2); + SegmentDatabaseDescriptor *d1 = (SegmentDatabaseDescriptor *) lfirst(a); + SegmentDatabaseDescriptor *d2 = (SegmentDatabaseDescriptor *) lfirst(b); return d1->identifier - d2->identifier; } @@ -1060,7 +1060,7 @@ gp_backend_info(PG_FUNCTION_ARGS) * For a slightly better default user experience, sort by descriptor ID. * Users may of course specify their own ORDER BY if they don't like it. */ - user_fctx->segdbs = list_qsort(user_fctx->segdbs, compare_segdb_id); + list_sort(user_fctx->segdbs, compare_segdb_id); user_fctx->curpos = list_head(user_fctx->segdbs); /* Create a descriptor for the records we'll be returning. */ @@ -1095,7 +1095,7 @@ gp_backend_info(PG_FUNCTION_ARGS) /* Get the next descriptor. */ dbdesc = lfirst(user_fctx->curpos); - user_fctx->curpos = lnext(user_fctx->curpos); + user_fctx->curpos = lnext(user_fctx->segdbs, user_fctx->curpos); /* Fill in the row attributes. */ dbinfo = dbdesc->segment_database_info; diff --git a/src/bin/gpfts/ftsprobe.c b/src/bin/gpfts/ftsprobe.c index ee0d8b746b4..8b110ba79a0 100644 --- a/src/bin/gpfts/ftsprobe.c +++ b/src/bin/gpfts/ftsprobe.c @@ -32,6 +32,7 @@ #include /* for MAXHOSTNAMELEN */ #include "fts_etcd.h" #include +#include "postmaster/postmaster.h" static struct pollfd *PollFds; @@ -284,8 +285,15 @@ checkIfConnFailedDueToRecoveryInProgress(PGconn *conn) && strstr(PQerrorMessage(conn),POSTMASTER_AFTER_PROMOTE_STANDBY_IN_RECOVERY_DETAIL_MSG); } +/* + * Check if the primary segment is restarting normally by examing the PQ error message. + * It could be that they are in RESET (waiting for the children to exit) or making + * progress in RECOVERY. Note there is no good source of RESET progress indications + * that we could check, so we simply always allow it. Normally RESET should be fast + * and there's a timeout in postmaster to guard against long wait. + */ static void -checkIfFailedDueToRecoveryInProgress(fts_segment_info *fts_info) +checkIfFailedDueToNormalRestart(fts_segment_info *fts_info) { if (strstr(PQerrorMessage(fts_info->conn), _(POSTMASTER_IN_RECOVERY_MSG)) || strstr(PQerrorMessage(fts_info->conn), _(POSTMASTER_IN_STARTUP_MSG))) @@ -322,6 +330,7 @@ checkIfFailedDueToRecoveryInProgress(fts_segment_info *fts_info) */ if (tmpptr <= fts_info->xlogrecptr) { + fts_info->restart_state = PM_IN_RECOVERY_NOT_MAKING_PROGRESS; cbdb_log_debug("detected segment is in recovery mode and not making progress (content=%d) " "primary dbid=%d, mirror dbid=%d", PRIMARY_CONFIG(fts_info)->segindex, @@ -330,7 +339,7 @@ checkIfFailedDueToRecoveryInProgress(fts_segment_info *fts_info) } else { - fts_info->recovery_making_progress = true; + fts_info->restart_state = PM_IN_RECOVERY_MAKING_PROGRESS; fts_info->xlogrecptr = tmpptr; cbdb_log_debug("detected segment is in recovery mode replayed (%X/%X) (content=%d) " @@ -342,6 +351,15 @@ checkIfFailedDueToRecoveryInProgress(fts_segment_info *fts_info) fts_info->has_mirror_configured ? MIRROR_CONFIG(fts_info)->dbid : -1); } } + else if (strstr(PQerrorMessage(fts_info->conn), _(POSTMASTER_IN_RESET_MSG))) + { + fts_info->restart_state = PM_IN_RESETTING; + cbdb_log_debug("FTS: detected segment is in RESET state (content=%d) " + "primary dbid=%d, mirror dbid=%d", + fts_info->primary_cdbinfo->config->segindex, + fts_info->primary_cdbinfo->config->dbid, + fts_info->mirror_cdbinfo->config->dbid); + } } /* @@ -376,10 +394,11 @@ ftsConnect(fts_context *context) case FTS_SYNCREP_OFF_SEGMENT: case FTS_PROMOTE_SEGMENT: /* - * We always default to false. If connect fails due to recovery in progress - * this variable will be set based on LSN value in error message. + * We always default to PM_NOT_IN_RESTART. If connect fails, we then check + * the primary's restarting state, so we can skip promoting mirror if it's in + * PM_IN_RESETTING or PM_IN_RECOVERY_MAKING_PROGRESS. */ - fts_info->recovery_making_progress = false; + fts_info->restart_state = PM_NOT_IN_RESTART; if (fts_info->conn == NULL) { Assert(fts_info->retry_count <= context->config->probe_retries); @@ -426,7 +445,7 @@ ftsConnect(fts_context *context) case PGRES_POLLING_FAILED: fts_info->state = nextFailedState(fts_info->state); - checkIfFailedDueToRecoveryInProgress(fts_info); + checkIfFailedDueToNormalRestart(fts_info); cbdb_log_debug("cannot establish libpq connection " "(content=%d, dbid=%d): %s, retry_count=%d", PRIMARY_CONFIG(fts_info)->segindex, @@ -1266,11 +1285,21 @@ processResponse(fts_context *context) } break; case FTS_PROBE_FAILED: - /* - * Primary is down - * If primary is in recovery, do not mark it down and promote mirror - */ - if (fts_info->recovery_making_progress) + /* Primary is down */ + + /* If primary is in resetting or making progress in recovery, do not mark it down and promote mirror */ + if (fts_info->restart_state == PM_IN_RESETTING) + { + Assert(strstr(PQerrorMessage(fts_info->conn), _(POSTMASTER_IN_RESET_MSG))); + cbdb_log_debug( + "FTS: detected segment is in resetting mode " + "(content=%d) primary dbid=%d, mirror dbid=%d", + primary->config->segindex, primary->config->dbid, mirror->config->dbid); + + fts_info->state = FTS_RESPONSE_PROCESSED; + break; + } + else if (fts_info->restart_state == PM_IN_RECOVERY_MAKING_PROGRESS) { assert(strstr(PQerrorMessage(fts_info->conn), _(POSTMASTER_IN_RECOVERY_MSG)) || strstr(PQerrorMessage(fts_info->conn), _(POSTMASTER_IN_STARTUP_MSG))); @@ -1467,7 +1496,7 @@ FtsWalRepInitProbeContext(CdbComponentDatabases *cdbs, fts_context *context, fts fts_info->state = FTS_PROBE_FAILED; else fts_info->state = FTS_PROBE_SEGMENT; - fts_info->recovery_making_progress = false; + fts_info->restart_state = PM_NOT_IN_RESTART; fts_info->xlogrecptr = InvalidXLogRecPtr; fts_info->primary_cdbinfo = primary; @@ -1495,7 +1524,7 @@ FtsWalRepInitProbeContext(CdbComponentDatabases *cdbs, fts_context *context, fts fts_info->state = FTS_PROBE_FAILED; else fts_info->state = FTS_PROBE_SEGMENT; - fts_info->recovery_making_progress = false; + fts_info->restart_state = PM_NOT_IN_RESTART; fts_info->xlogrecptr = InvalidXLogRecPtr; fts_info->primary_cdbinfo = master; diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index ca6c907dbe2..589b54e30ca 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -56,6 +56,6 @@ */ /* 3yyymmddN */ -#define CATALOG_VERSION_NO 302208261 +#define CATALOG_VERSION_NO 302405281 #endif diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index cd4616b8fbb..a4ebb62805d 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -11973,7 +11973,7 @@ { oid => 7182, descr => 'wait until all endpoint of this parallel retrieve cursor has been retrieved finished', proname => 'gp_wait_parallel_retrieve_cursor', provolatile => 'v', proparallel => 'u', prorettype => 'bool', proargtypes => 'text int4', proallargtypes => '{text,int4,bool}', proargmodes => '{i,i,o}', proargnames => '{cursorname,timeout_sec,finished}', prosrc => 'gp_wait_parallel_retrieve_cursor', proexeclocation => 'c' }, -{ oid => 7183, descr => 'debugging information for segment backends', +{ oid => 7146, descr => 'debugging information for segment backends', proname => 'gp_backend_info', prorettype => 'record', prorows => '1', proretset => 't', proargtypes => '', proallargtypes => '{int4,char,int4,text,int4,int4}', prosrc => 'gp_backend_info', pronargs => 6, proargnames => '{id,type,content,host,port,pid}', proargmodes => '{o,o,o,o,o,o}', proexeclocation => 'c'} diff --git a/src/test/isolation2/expected/fts_segment_reset.out b/src/test/isolation2/expected/fts_segment_reset.out index 8d575ccfddc..47cd2fa8294 100644 --- a/src/test/isolation2/expected/fts_segment_reset.out +++ b/src/test/isolation2/expected/fts_segment_reset.out @@ -53,8 +53,7 @@ CREATE 1<: <... completed> ERROR: fault triggered, fault name:'start_prepare' fault type:'panic' 2<: <... completed> -DETAIL: Segments are in reset/recovery mode. -ERROR: failed to acquire resources on one or more segments +CREATE -- We shouldn't see failover to mirror select gp_request_fts_probe_scan(); diff --git a/src/test/regress/expected/gp_prepared_xacts.out b/src/test/regress/expected/gp_prepared_xacts.out index b3a1b96bc46..217f941f0f4 100644 --- a/src/test/regress/expected/gp_prepared_xacts.out +++ b/src/test/regress/expected/gp_prepared_xacts.out @@ -1,7 +1,7 @@ -- PREPARE TRANSACTION should not work BEGIN; PREPARE TRANSACTION 'foo_prep_xact'; -ERROR: PREPARE TRANSACTION is not yet supported in Greenplum Database +ERROR: PREPARE TRANSACTION is not yet supported in Cloudberry Database -- PREPARE TRANSACTION should not work in utility-mode connections either \! PGOPTIONS='-c gp_role=utility' psql -X regression -c "BEGIN; PREPARE TRANSACTION 'foo_prep_xact';" ERROR: PREPARE TRANSACTION is not supported in utility mode diff --git a/src/test/regress/input/dispatch.source b/src/test/regress/input/dispatch.source index d058b8ea619..4068dc944e1 100644 --- a/src/test/regress/input/dispatch.source +++ b/src/test/regress/input/dispatch.source @@ -575,10 +575,6 @@ set optimizer=off; --gang reused create table t_create_gang_time(tc1 int,tc2 int); ---1-gang reused -select * from t_create_gang_time where tc1=1; -explain analyze select * from t_create_gang_time where tc1=1; - --n-gang reused and 1-gang is created. select * from t_create_gang_time t1, t_create_gang_time t2 where t1.tc1=2; diff --git a/src/test/regress/output/dispatch.source b/src/test/regress/output/dispatch.source index 4c94628f706..cd8d872d868 100644 --- a/src/test/regress/output/dispatch.source +++ b/src/test/regress/output/dispatch.source @@ -933,28 +933,6 @@ create table t_create_gang_time(tc1 int,tc2 int); NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'tc1' as the Greenplum Database data distribution key for this table. HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. INFO: (Gang) is reused ---1-gang reused -select * from t_create_gang_time where tc1=1; -INFO: (Slice1) is reused - tc1 | tc2 ------+----- -(0 rows) - -explain analyze select * from t_create_gang_time where tc1=1; -INFO: (Slice1) is reused - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------- - Gather Motion 1:1 (slice1; segments: 1) (cost=0.00..393.90 rows=86 width=8) (actual time=0.611..0.618 rows=0 loops=1) - -> Seq Scan on t_create_gang_time (cost=0.00..392.75 rows=29 width=8) (never executed) - Filter: (tc1 = 1) - Optimizer: Postgres query optimizer - Planning Time: 0.187 ms - (slice0) Executor memory: 36K bytes. - (slice1) Executor memory: 36K bytes (seg1). - Memory used: 128000kB - Execution Time: 1.249 ms -(9 rows) - --n-gang reused and 1-gang is created. select * from t_create_gang_time t1, t_create_gang_time t2 where t1.tc1=2; INFO: (Slice1) is reused diff --git a/src/test/singlenode_regress/expected/memoize.out b/src/test/singlenode_regress/expected/memoize.out index 3ce36a5342d..89ee1727670 100644 --- a/src/test/singlenode_regress/expected/memoize.out +++ b/src/test/singlenode_regress/expected/memoize.out @@ -116,7 +116,7 @@ WHERE t2.unique1 < 1200;', true); Heap Fetches: N -> Sort (actual rows=1200 loops=N) Sort Key: t2.thousand - Sort Method: external sort Disk: 64kB + Sort Method: quicksort Memory: NkB -> Seq Scan on tenk1 t2 (actual rows=1200 loops=N) Filter: (unique1 < 1200) Rows Removed by Filter: 8800 diff --git a/src/test/singlenode_regress/expected/query_finish_pending.out b/src/test/singlenode_regress/expected/query_finish_pending.out index 879ac9a1bde..12e26f6c36a 100644 --- a/src/test/singlenode_regress/expected/query_finish_pending.out +++ b/src/test/singlenode_regress/expected/query_finish_pending.out @@ -24,8 +24,7 @@ select gp_inject_fault('execsort_sort_mergeruns', 'finish_pending', 1); select DISTINCT S from (select row_number() over(partition by i1 order by i2) AS T, count(*) over (partition by i1) AS S from _tmp_table) AS TMP; s --- - 1 -(1 row) +(0 rows) -- In single node, merge run won't be triggered. -- start_ignore @@ -53,8 +52,7 @@ select gp_inject_fault('execsort_dumptuples', 'finish_pending', 1); select DISTINCT S from (select row_number() over(partition by i1 order by i2) AS T, count(*) over (partition by i1) AS S from _tmp_table) AS TMP; s --- - 1 -(1 row) +(0 rows) -- In single node, merge run won't be triggered. -- start_ignore diff --git a/src/test/singlenode_regress/expected/temp.out b/src/test/singlenode_regress/expected/temp.out index af76a4564d1..69b4ebfe116 100644 --- a/src/test/singlenode_regress/expected/temp.out +++ b/src/test/singlenode_regress/expected/temp.out @@ -328,7 +328,7 @@ begin; create function pg_temp.twophase_func() returns void as $$ select '2pc_func'::text $$ language sql; prepare transaction 'twophase_func'; -ERROR: PREPARE TRANSACTION is not yet supported in Cloudberry Database +ERROR: PREPARE TRANSACTION is not supported in utility mode rollback; -- PREPARE TRANACTION is not supported in GPDB -- Function drop create function pg_temp.twophase_func() returns void as @@ -336,29 +336,29 @@ create function pg_temp.twophase_func() returns void as begin; drop function pg_temp.twophase_func(); prepare transaction 'twophase_func'; -ERROR: PREPARE TRANSACTION is not yet supported in Cloudberry Database +ERROR: PREPARE TRANSACTION is not supported in utility mode rollback; -- PREPARE TRANACTION is not supported in GPDB -- Operator creation begin; create operator pg_temp.@@ (leftarg = int4, rightarg = int4, procedure = int4mi); prepare transaction 'twophase_operator'; -ERROR: PREPARE TRANSACTION is not yet supported in Cloudberry Database +ERROR: PREPARE TRANSACTION is not supported in utility mode rollback; -- PREPARE TRANACTION is not supported in GPDB -- These generate errors about temporary tables. begin; create type pg_temp.twophase_type as (a int); prepare transaction 'twophase_type'; -ERROR: PREPARE TRANSACTION is not yet supported in Cloudberry Database +ERROR: PREPARE TRANSACTION is not supported in utility mode rollback; -- PREPARE TRANACTION is not supported in GPDB begin; create view pg_temp.twophase_view as select 1; prepare transaction 'twophase_view'; -ERROR: PREPARE TRANSACTION is not yet supported in Cloudberry Database +ERROR: PREPARE TRANSACTION is not supported in utility mode rollback; -- PREPARE TRANACTION is not supported in GPDB begin; create sequence pg_temp.twophase_seq; prepare transaction 'twophase_sequence'; -ERROR: PREPARE TRANSACTION is not yet supported in Cloudberry Database +ERROR: PREPARE TRANSACTION is not supported in utility mode rollback; -- PREPARE TRANACTION is not supported in GPDB -- Temporary tables cannot be used with two-phase commit. create temp table twophase_tab (a int); @@ -369,22 +369,22 @@ select a from twophase_tab; (0 rows) prepare transaction 'twophase_tab'; -ERROR: PREPARE TRANSACTION is not yet supported in Cloudberry Database +ERROR: PREPARE TRANSACTION is not supported in utility mode rollback; -- PREPARE TRANACTION is not supported in GPDB begin; insert into twophase_tab values (1); prepare transaction 'twophase_tab'; -ERROR: PREPARE TRANSACTION is not yet supported in Cloudberry Database +ERROR: PREPARE TRANSACTION is not supported in utility mode rollback; -- PREPARE TRANACTION is not supported in GPDB begin; lock twophase_tab in access exclusive mode; prepare transaction 'twophase_tab'; -ERROR: PREPARE TRANSACTION is not yet supported in Cloudberry Database +ERROR: PREPARE TRANSACTION is not supported in utility mode rollback; -- PREPARE TRANACTION is not supported in GPDB begin; drop table twophase_tab; prepare transaction 'twophase_tab'; -ERROR: PREPARE TRANSACTION is not yet supported in Cloudberry Database +ERROR: PREPARE TRANSACTION is not supported in utility mode rollback; -- PREPARE TRANACTION is not supported in GPDB -- Corner case: current_schema may create a temporary schema if namespace -- creation is pending, so check after that. First reset the connection @@ -399,4 +399,4 @@ SELECT current_schema() ~ 'pg_temp' AS is_temp_schema; (1 row) PREPARE TRANSACTION 'twophase_search'; -ERROR: PREPARE TRANSACTION is not yet supported in Cloudberry Database +ERROR: PREPARE TRANSACTION is not supported in utility mode