diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index f505413a7f..08ea67ff41 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -7611,19 +7611,27 @@ set_config_option(const char *name, const char *value,
 												  &newval_union, &newextra))
 						return 0;
 				}
-				else if (source == PGC_S_DEFAULT)
+				else
 				{
-					newval = conf->boot_val;
+					if (source != PGC_S_DEFAULT)
+						newval = conf->reset_val;
+					else
+						newval = conf->boot_val;
+
 					if (!call_bool_check_hook(conf, &newval, &newextra,
 											  source, elevel))
 						return 0;
-				}
-				else
-				{
-					newval = conf->reset_val;
-					newextra = conf->reset_extra;
-					source = conf->gen.reset_source;
-					context = conf->gen.reset_scontext;
+
+					if (source != PGC_S_DEFAULT)
+					{
+						/* Release newextra as we use reset_extra */
+						if (newextra)
+							free(newextra);
+
+						newextra = conf->reset_extra;
+						source = conf->gen.reset_source;
+						context = conf->gen.reset_scontext;
+					}
 				}
 
 				if (prohibitValueChange)
@@ -7705,19 +7713,30 @@ set_config_option(const char *name, const char *value,
 												  &newval_union, &newextra))
 						return 0;
 				}
-				else if (source == PGC_S_DEFAULT)
+				else
 				{
-					newval = conf->boot_val;
+					if (source != PGC_S_DEFAULT)
+						newval = conf->reset_val;
+					else
+						newval = conf->boot_val;
+
 					if (!call_int_check_hook(conf, &newval, &newextra,
 											 source, elevel))
 						return 0;
-				}
-				else
-				{
-					newval = conf->reset_val;
-					newextra = conf->reset_extra;
-					source = conf->gen.reset_source;
-					context = conf->gen.reset_scontext;
+
+					if (source != PGC_S_DEFAULT)
+					{
+						/* Release newextra as we use reset_extra */
+						if (newextra)
+						{
+							Assert(!extra_field_used(&conf->gen, newextra));
+							free(newextra);
+						}
+
+						newextra = conf->reset_extra;
+						source = conf->gen.reset_source;
+						context = conf->gen.reset_scontext;
+					}
 				}
 
 				if (prohibitValueChange)
@@ -7799,19 +7818,27 @@ set_config_option(const char *name, const char *value,
 												  &newval_union, &newextra))
 						return 0;
 				}
-				else if (source == PGC_S_DEFAULT)
+				else
 				{
-					newval = conf->boot_val;
+					if (source != PGC_S_DEFAULT)
+						newval = conf->reset_val;
+					else
+						newval = conf->boot_val;
+
 					if (!call_real_check_hook(conf, &newval, &newextra,
 											  source, elevel))
 						return 0;
-				}
-				else
-				{
-					newval = conf->reset_val;
-					newextra = conf->reset_extra;
-					source = conf->gen.reset_source;
-					context = conf->gen.reset_scontext;
+
+					if (source != PGC_S_DEFAULT)
+					{
+						/* Release newextra as we use reset_extra */
+						if (newextra)
+							free(newextra);
+
+						newextra = conf->reset_extra;
+						source = conf->gen.reset_source;
+						context = conf->gen.reset_scontext;
+					}
 				}
 
 				if (prohibitValueChange)
@@ -7893,17 +7920,20 @@ set_config_option(const char *name, const char *value,
 												  &newval_union, &newextra))
 						return 0;
 				}
-				else if (source == PGC_S_DEFAULT)
+				else
 				{
-					/* non-NULL boot_val must always get strdup'd */
-					if (conf->boot_val != NULL)
+					if (source != PGC_S_DEFAULT)
+						newval = conf->reset_val;
+					else
+						newval = conf->boot_val;
+
+					/* non-NULL value must always get strdup'd */
+					if (newval)
 					{
-						newval = guc_strdup(elevel, conf->boot_val);
+						newval = guc_strdup(elevel, newval);
 						if (newval == NULL)
 							return 0;
 					}
-					else
-						newval = NULL;
 
 					if (!call_string_check_hook(conf, &newval, &newextra,
 												source, elevel))
@@ -7911,17 +7941,22 @@ set_config_option(const char *name, const char *value,
 						free(newval);
 						return 0;
 					}
-				}
-				else
-				{
-					/*
-					 * strdup not needed, since reset_val is already under
-					 * guc.c's control
-					 */
-					newval = conf->reset_val;
-					newextra = conf->reset_extra;
-					source = conf->gen.reset_source;
-					context = conf->gen.reset_scontext;
+
+					if (source != PGC_S_DEFAULT)
+					{
+						/* Release newextra as we use reset_extra */
+						if (newextra)
+							free(newextra);
+
+						/*
+						 * strdup not needed, since reset_val is already under
+						 * guc.c's control
+						 */
+						newval = conf->reset_val;
+						newextra = conf->reset_extra;
+						source = conf->gen.reset_source;
+						context = conf->gen.reset_scontext;
+					}
 				}
 
 				if (prohibitValueChange)
@@ -8018,19 +8053,27 @@ set_config_option(const char *name, const char *value,
 												  &newval_union, &newextra))
 						return 0;
 				}
-				else if (source == PGC_S_DEFAULT)
+				else
 				{
-					newval = conf->boot_val;
+					if (source != PGC_S_DEFAULT)
+						newval = conf->reset_val;
+					else
+						newval = conf->boot_val;
+
 					if (!call_enum_check_hook(conf, &newval, &newextra,
 											  source, elevel))
 						return 0;
-				}
-				else
-				{
-					newval = conf->reset_val;
-					newextra = conf->reset_extra;
-					source = conf->gen.reset_source;
-					context = conf->gen.reset_scontext;
+
+					if (source != PGC_S_DEFAULT)
+					{
+						/* Release newextra as we use reset_extra */
+						if (newextra)
+							free(newextra);
+
+						newextra = conf->reset_extra;
+						source = conf->gen.reset_source;
+						context = conf->gen.reset_scontext;
+					}
 				}
 
 				if (prohibitValueChange)
diff --git a/src/test/regress/expected/transactions.out b/src/test/regress/expected/transactions.out
index 61862d595d..1f301f3033 100644
--- a/src/test/regress/expected/transactions.out
+++ b/src/test/regress/expected/transactions.out
@@ -40,6 +40,38 @@ SELECT * FROM aggtest;
   42 |  324.78
 (4 rows)
 
+-- Test that we disallow changing transaction characteristics after the
+-- first snapshot acquisition.
+BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- ok
+SELECT count(*) FROM xacttest; -- ok
+ count 
+-------
+     5
+(1 row)
+
+RESET transaction_isolation; -- fail
+ERROR:  SET TRANSACTION ISOLATION LEVEL must be called before any query
+COMMIT;
+BEGIN TRANSACTION READ ONLY; -- ok
+SELECT count(*) FROM xacttest; -- ok
+ count 
+-------
+     5
+(1 row)
+
+RESET transaction_read_only; -- fail
+ERROR:  transaction read-write mode must be set before any query
+COMMIT;
+BEGIN TRANSACTION DEFERRABLE; -- ok
+SELECT count(*) FROM xacttest; -- ok
+ count 
+-------
+     5
+(1 row)
+
+RESET transaction_deferrable; -- fail
+ERROR:  SET TRANSACTION [NOT] DEFERRABLE must be called before any query
+COMMIT;
 -- Read-only tests
 CREATE TABLE writetest (a int);
 CREATE TEMPORARY TABLE temptest (a int);
diff --git a/src/test/regress/sql/transactions.sql b/src/test/regress/sql/transactions.sql
index 8886280c0a..b4b9b43f77 100644
--- a/src/test/regress/sql/transactions.sql
+++ b/src/test/regress/sql/transactions.sql
@@ -33,6 +33,22 @@ SELECT oid FROM pg_class WHERE relname = 'disappear';
 -- should have members again
 SELECT * FROM aggtest;
 
+-- Test that we disallow changing transaction characteristics after the
+-- first snapshot acquisition.
+BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- ok
+SELECT count(*) FROM xacttest; -- ok
+RESET transaction_isolation; -- fail
+COMMIT;
+
+BEGIN TRANSACTION READ ONLY; -- ok
+SELECT count(*) FROM xacttest; -- ok
+RESET transaction_read_only; -- fail
+COMMIT;
+
+BEGIN TRANSACTION DEFERRABLE; -- ok
+SELECT count(*) FROM xacttest; -- ok
+RESET transaction_deferrable; -- fail
+COMMIT;
 
 -- Read-only tests
 
