Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pI5dZ-0003uS-Av for pgsql-hackers@arkaria.postgresql.org; Wed, 18 Jan 2023 10:25:45 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1pI5dY-0006EK-7M for pgsql-hackers@arkaria.postgresql.org; Wed, 18 Jan 2023 10:25:44 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pI5dX-0006Dc-OJ for pgsql-hackers@lists.postgresql.org; Wed, 18 Jan 2023 10:25:43 +0000 Received: from mail-wr1-x434.google.com ([2a00:1450:4864:20::434]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1pI5dU-0005oz-Mx for pgsql-hackers@postgresql.org; Wed, 18 Jan 2023 10:25:42 +0000 Received: by mail-wr1-x434.google.com with SMTP id d2so13296429wrp.8 for ; Wed, 18 Jan 2023 02:25:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:in-reply-to:content-language:references :cc:to:subject:from:user-agent:mime-version:date:message-id:from:to :cc:subject:date:message-id:reply-to; bh=Iqkm+FA4LGIpqC5FZbcxr/KoXU/cC9r2VqpZb/vAQ5o=; b=oRU1I+ZpLZ3KkVHsDaNyc1foQOzllJAyKiU8shv8HCEsdBQsAP6PQBNCCXzExMp7O7 3NwzU9K2hzIURFVW7sOuSF3fivoGRHgihLz8A/BxE80mmyeu0YZS6j81tJPMh57gcgZy hU1O36MMliCxUMogK7GQImtToiy3eYa5MDZ2R9Qpnayc5Xb66DQpggj+KQ8ZxMMaQfcY f3KdNTCim0YTG48Hsk7jpERZhUiig8eW9RJMuAzcDbp2kGxW+ntjU27I3l6IBtquwfEt GXD8L2TkYwND6dCl0UpxCLE3eCNFffPAdWzzL12zdaIfYSnRA/tMJoSyJrW/XRDWG6Bw g+2g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:in-reply-to:content-language:references :cc:to:subject:from:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Iqkm+FA4LGIpqC5FZbcxr/KoXU/cC9r2VqpZb/vAQ5o=; b=KLHQ3D5auwQU0Ai17dLQX+/fjWK3XN94N314Wq594G0hQPEeVADzCLEs1QtITcjBBO 534uZVfz8wrI/dgBwy20bDBm7CyLPvqcTraxuzRTaDJJ8cs0Jm0ugpNulkCcoO2/sMmy FWisDahuxxL1Sf27wq04Cj83yvWAS4wBPEQnXS0iaa/r4/eWrsRWMrCd/3yqmrzdgaxP 6FVHZy+WF6HvdNoxbeQDMBnRvoXsiamZN/x0I0Ux6Jq7u9wW49vLXZ0uq2As7fV5YRCP ymTwIRG7Xu3rloRxPWzAmL9P6wp6PSO950OqsPFPw8if0KiK7zDrxh3isSKOy055Yi6n 7dTw== X-Gm-Message-State: AFqh2kqkH14S3T40wygOCg43vZ/90tZ/7E344ovtJjkjFJE3Ru7fMd+5 xEeZ3fkMt+8RkMRn3A68FYc= X-Google-Smtp-Source: AMrXdXuRgDeejBOKdKUtujHBFVX5cHbMnnFBRFuFU9qVpkvpQWgNZ0GLwpoXmoAWKArY0H+SS2WlKA== X-Received: by 2002:adf:de81:0:b0:2bd:dc5c:7e4c with SMTP id w1-20020adfde81000000b002bddc5c7e4cmr5589678wrl.15.1674037538461; Wed, 18 Jan 2023 02:25:38 -0800 (PST) Received: from [192.168.3.188] ([54.239.6.189]) by smtp.gmail.com with ESMTPSA id m13-20020adfe94d000000b002714b3d2348sm31061090wrn.25.2023.01.18.02.25.35 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 18 Jan 2023 02:25:35 -0800 (PST) Message-ID: <490206c5-bcde-e558-628a-dc67dae4d439@gmail.com> Date: Wed, 18 Jan 2023 11:24:19 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:102.0) Gecko/20100101 Thunderbird/102.6.1 From: "Drouvot, Bertrand" Subject: Re: Minimal logical decoding on standbys To: Andres Freund , Robert Haas , Thomas Munro Cc: Alvaro Herrera , Ibrar Ahmed , Amit Khandekar , fabriziomello@gmail.com, tushar , Rahila Syed , pgsql-hackers References: <20221214173552.sshklqvwezeo52h3@alap3.anarazel.de> <1f2ad9fd-53ff-74cc-a602-72d45423bcab@gmail.com> <05c0c4f3-82eb-bc6d-c876-5a265c05927b@gmail.com> <20230106034036.2m4qnn7ep7b5ipet@awork3.anarazel.de> Content-Language: en-US In-Reply-To: <20230106034036.2m4qnn7ep7b5ipet@awork3.anarazel.de> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Hi, On 1/6/23 4:40 AM, Andres Freund wrote: > Hi, > 0004: > >> @@ -3037,6 +3037,43 @@ $SIG{TERM} = $SIG{INT} = sub { >> >> =pod >> >> +=item $node->create_logical_slot_on_standby(self, master, slot_name, dbname) >> + >> +Create logical replication slot on given standby >> + >> +=cut >> + >> +sub create_logical_slot_on_standby >> +{ > > Any reason this has to be standby specific? > Due to the extra work to be done for this case (aka wait for restart_lsn and trigger a checkpoint on the primary). > >> + # Now arrange for the xl_running_xacts record for which pg_recvlogical >> + # is waiting. >> + $master->safe_psql('postgres', 'CHECKPOINT'); >> + > > Hm, that's quite expensive. Perhaps worth adding a C helper that can do that > for us instead? This will likely also be needed in real applications after all. > Not sure I got it. What the C helper would be supposed to do? > >> + print "starting pg_recvlogical\n"; > > I don't think tests should just print somewhere. Either diag() or note() > should be used. > > Will be done. >> + if ($wait) >> + # make sure activeslot is in use >> + { >> + $node_standby->poll_query_until('testdb', >> + "SELECT EXISTS (SELECT 1 FROM pg_replication_slots WHERE slot_name = 'activeslot' AND active_pid IS NOT NULL)" >> + ) or die "slot never became active"; >> + } > > That comment placement imo is quite odd. > > Agree, will be done. >> +# test if basic decoding works >> +is(scalar(my @foobar = split /^/m, $result), >> + 14, 'Decoding produced 14 rows'); > > Maybe mention that it's 2 transactions + 10 rows? > > Agree, will be done. >> +$node_primary->wait_for_catchup($node_standby, 'replay', $node_primary->lsn('flush')); > > There's enough copies of this that I wonder if we shouldn't introduce a > Cluster.pm level helper for this. > Done in [1]. > >> +print "waiting to replay $endpos\n"; > > See above. > > Will be done. >> +my $stdout_recv = $node_standby->pg_recvlogical_upto( >> + 'testdb', 'activeslot', $endpos, 180, >> + 'include-xids' => '0', >> + 'skip-empty-xacts' => '1'); > > I don't think this should use a hardcoded 180 but > $PostgreSQL::Test::Utils::timeout_default. > > Agree, will be done. >> +# One way to reproduce recovery conflict is to run VACUUM FULL with >> +# hot_standby_feedback turned off on the standby. >> +$node_standby->append_conf('postgresql.conf',q[ >> +hot_standby_feedback = off >> +]); >> +$node_standby->restart; > > IIRC a reload should suffice. > > Right. With a reload in place in my testing, now I notice that the catalog_xmin is updated on the primary physical slot after logical slots invalidation when reloading hot_standby_feedback from "off" to "on". This is not the case after a re-start (aka catalog_xmin is NULL). I think a re-start and reload should produce identical behavior on the primary physical slot. If so, I'm tempted to think that the catalog_xmin should be updated in case of a re-start too (even if all the logical slots are invalidated) because the slots are not dropped yet. What do you think? >> +# This should trigger the conflict >> +$node_primary->safe_psql('testdb', 'VACUUM FULL'); > > Can we do something cheaper than rewriting the entire database? Seems > rewriting a single table ought to be sufficient? > While implementing the test at the table level I discovered that It looks like there is no guarantee that say a "vacuum full pg_class;" would produce a conflict. Indeed, from what I can see in my testing it could generate a XLOG_HEAP2_PRUNE with snapshotConflictHorizon to 0: "rmgr: Heap2 len (rec/tot): 107/ 107, tx: 848, lsn: 0/03B98B30, prev 0/03B98AF0, desc: PRUNE snapshotConflictHorizon 0" Having a snapshotConflictHorizon to zero leads to ResolveRecoveryConflictWithSnapshot() simply returning without any conflict handling. It does look like that in the standby decoding case that's not the right behavior (and that the xid that generated the PRUNING should be used instead) , what do you think? > I think it'd also be good to test that rewriting a non-catalog table doesn't > trigger an issue. > > Good point, but need to understand the above first. >> +################################################## >> +# Recovery conflict: Invalidate conflicting slots, including in-use slots >> +# Scenario 2: conflict due to row removal with hot_standby_feedback off. >> +################################################## >> + >> +# get the position to search from in the standby logfile >> +my $logstart = -s $node_standby->logfile; >> + >> +# drop the logical slots >> +$node_standby->psql('postgres', q[SELECT pg_drop_replication_slot('inactiveslot')]); >> +$node_standby->psql('postgres', q[SELECT pg_drop_replication_slot('activeslot')]); >> + >> +create_logical_slots(); >> + >> +# One way to produce recovery conflict is to create/drop a relation and launch a vacuum >> +# with hot_standby_feedback turned off on the standby. >> +$node_standby->append_conf('postgresql.conf',q[ >> +hot_standby_feedback = off >> +]); >> +$node_standby->restart; >> +# ensure walreceiver feedback off by waiting for expected xmin and >> +# catalog_xmin on primary. Both should be NULL since hs_feedback is off >> +wait_for_xmins($node_primary, $primary_slotname, >> + "xmin IS NULL AND catalog_xmin IS NULL"); >> + >> +$handle = make_slot_active(1); > > This is a fair bit of repeated setup, maybe put it into a function? > > Yeah, good point: will be done. > I think it'd be good to test the ongoing decoding via the SQL interface also > gets correctly handled. But it might be too hard to do reliably. > > >> +################################################## >> +# Test standby promotion and logical decoding behavior >> +# after the standby gets promoted. >> +################################################## >> + > > I think this also should test the streaming / walsender case. > Do you mean cascading standby? Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com [1]: https://www.postgresql.org/message-id/flat/846724b5-0723-f4c2-8b13-75301ec7509e%40gmail.com