mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Disallow starting server with insufficient wal_level for existing slot.
Previously it was possible to create a slot, change wal_level, and restart, even if the new wal_level was insufficient for the slot. That's a problem for both logical and physical slots, because the necessary WAL records are not generated. This removes a few tests in newer versions that, somewhat inexplicably, whether restarting with a too low wal_level worked (a buggy behaviour!). Reported-By: Joshua D. Drake Author: Andres Freund Discussion: https://postgr.es/m/20181029191304.lbsmhshkyymhw22w@alap3.anarazel.de Backpatch: 9.4-, where replication slots where introduced
This commit is contained in:
		@@ -79,6 +79,11 @@ CheckLogicalDecodingRequirements(void)
 | 
			
		||||
{
 | 
			
		||||
	CheckSlotRequirements();
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * NB: Adding a new requirement likely means that RestoreSlotFromDisk()
 | 
			
		||||
	 * needs the same check.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	if (wal_level < WAL_LEVEL_LOGICAL)
 | 
			
		||||
		ereport(ERROR,
 | 
			
		||||
				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
 | 
			
		||||
 
 | 
			
		||||
@@ -972,6 +972,11 @@ restart:
 | 
			
		||||
void
 | 
			
		||||
CheckSlotRequirements(void)
 | 
			
		||||
{
 | 
			
		||||
	/*
 | 
			
		||||
	 * NB: Adding a new requirement likely means that RestoreSlotFromDisk()
 | 
			
		||||
	 * needs the same check.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	if (max_replication_slots == 0)
 | 
			
		||||
		ereport(ERROR,
 | 
			
		||||
				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
 | 
			
		||||
@@ -1493,6 +1498,31 @@ RestoreSlotFromDisk(const char *name)
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Verify that requirements for the specific slot type are met. That's
 | 
			
		||||
	 * important because if these aren't met we're not guaranteed to retain
 | 
			
		||||
	 * all the necessary resources for the slot.
 | 
			
		||||
	 *
 | 
			
		||||
	 * NB: We have to do so *after* the above checks for ephemeral slots,
 | 
			
		||||
	 * because otherwise a slot that shouldn't exist anymore could prevent
 | 
			
		||||
	 * restarts.
 | 
			
		||||
	 *
 | 
			
		||||
	 * NB: Changing the requirements here also requires adapting
 | 
			
		||||
	 * CheckSlotRequirements() and CheckLogicalDecodingRequirements().
 | 
			
		||||
	 */
 | 
			
		||||
	if (cp.slotdata.database != InvalidOid && wal_level < WAL_LEVEL_LOGICAL)
 | 
			
		||||
		ereport(FATAL,
 | 
			
		||||
				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
 | 
			
		||||
				 errmsg("logical replication slots \"%s\" exists, but wal_level < logical",
 | 
			
		||||
						NameStr(cp.slotdata.name)),
 | 
			
		||||
				 errhint("Change wal_level to be replica or higher.")));
 | 
			
		||||
	else if (wal_level < WAL_LEVEL_REPLICA)
 | 
			
		||||
		ereport(FATAL,
 | 
			
		||||
				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
 | 
			
		||||
				 errmsg("physical replication slots \"%s\" exists, but wal_level < replica",
 | 
			
		||||
						NameStr(cp.slotdata.name)),
 | 
			
		||||
				 errhint("Change wal_level to be replica or higher.")));
 | 
			
		||||
 | 
			
		||||
	/* nothing can be active yet, don't lock anything */
 | 
			
		||||
	for (i = 0; i < max_replication_slots; i++)
 | 
			
		||||
	{
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user