Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.92) (envelope-from ) id 1j9W4q-0008R9-3t for pgsql-hackers@arkaria.postgresql.org; Wed, 04 Mar 2020 15:36:53 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1j9W4n-0000jq-LF for pgsql-hackers@arkaria.postgresql.org; Wed, 04 Mar 2020 15:36:49 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1j9W4n-0000jd-AH for pgsql-hackers@lists.postgresql.org; Wed, 04 Mar 2020 15:36:49 +0000 Received: from cyclops.postgrespro.ru ([93.174.131.138] helo=mail.postgrespro.ru) by magus.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1j9W4k-0005ws-Na for pgsql-hackers@lists.postgresql.org; Wed, 04 Mar 2020 15:36:48 +0000 Received: from localhost (localhost [127.0.0.1]) by mail.postgrespro.ru (Postfix) with ESMTP id 2A13A21C1D3A; Wed, 4 Mar 2020 18:36:45 +0300 (MSK) X-Virus-Scanned: Debian amavisd-new at postgrespro.ru X-Spam-Flag: NO X-Spam-Score: 0 X-Spam-Level: X-Spam-Status: No, score=x tagged_above=-99 required=4 WHITELISTED tests=[] autolearn=unavailable Received: from ars-thinkpad (nat03-43-2.netorn.net [188.35.130.88]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mail.postgrespro.ru (Postfix) with ESMTPSA id E8FC821C1C2D; Wed, 4 Mar 2020 18:36:44 +0300 (MSK) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=postgrespro.ru; s=mail; t=1583336204; bh=UAr7scjPnz+/Z6A6zZXKmBve6f3/iMR+A+g5qFlobm4=; h=References:From:To:Cc:Subject:In-reply-to:Date; b=Cv0P2WaxO4seDKaFmwEpUXyJANrEEzvLLeYfoCo5Pbg+rmsNGl0UG0DE3I7IrHGiZ hsxKg+iFmXK8jrQgn/zpIMcmy7/NILTjR8WSP9Y1xy8L15SNE+PqpyadALEUL+5/gy OHHhjVpzC3sabXSVB1zhWx2f8Z5SW2X6UmefY740= References: <871rr3ohbo.fsf@ars-thinkpad> <87v9oelex6.fsf@ars-thinkpad> User-agent: mu4e 1.2.0; emacs 26.0.50 From: Arseny Sher To: pgsql-hackers@lists.postgresql.org Cc: PostgreSQL Hackers , Alvaro Herrera Subject: Re: logical copy_replication_slot issues In-reply-to: Date: Wed, 04 Mar 2020 18:36:44 +0300 Message-ID: <87k1406sj7.fsf@ars-thinkpad> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --=-=-= Content-Type: text/plain Masahiko Sawada writes: > I've attached the updated version patch that incorporated your > comments. I believe we're going in the right direction for fixing this > bug. I'll register this item to the next commit fest so as not to > forget. I've moved confirmed_flush check to the second lookup out of paranoic considerations (e.g. slot could have been recreated and creation hasn't finished yet) and made some minor stylistic adjustments. It looks good to me now. --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=fix_copy_slot_v3.patch diff --git a/src/backend/replication/slotfuncs.c b/src/backend/replication/slotfuncs.c index 2c9d5de6d9..4a3c7aa0ce 100644 --- a/src/backend/replication/slotfuncs.c +++ b/src/backend/replication/slotfuncs.c @@ -121,7 +121,8 @@ pg_create_physical_replication_slot(PG_FUNCTION_ARGS) */ static void create_logical_replication_slot(char *name, char *plugin, - bool temporary, XLogRecPtr restart_lsn) + bool temporary, XLogRecPtr restart_lsn, + bool find_startpoint) { LogicalDecodingContext *ctx = NULL; @@ -139,16 +140,18 @@ create_logical_replication_slot(char *name, char *plugin, temporary ? RS_TEMPORARY : RS_EPHEMERAL); /* - * Create logical decoding context, to build the initial snapshot. + * Create logical decoding context to find start point or, if we don't + * need it, to 1) bump slot's restart_lsn 2) check plugin sanity. */ ctx = CreateInitDecodingContext(plugin, NIL, - false, /* do not build snapshot */ + false, /* do not build data snapshot */ restart_lsn, logical_read_local_xlog_page, NULL, NULL, NULL); /* build initial snapshot, might take a while */ - DecodingContextFindStartpoint(ctx); + if (find_startpoint) + DecodingContextFindStartpoint(ctx); /* don't need the decoding context anymore */ FreeDecodingContext(ctx); @@ -179,7 +182,8 @@ pg_create_logical_replication_slot(PG_FUNCTION_ARGS) create_logical_replication_slot(NameStr(*name), NameStr(*plugin), temporary, - InvalidXLogRecPtr); + InvalidXLogRecPtr, + true); values[0] = NameGetDatum(&MyReplicationSlot->data.name); values[1] = LSNGetDatum(MyReplicationSlot->data.confirmed_flush); @@ -683,10 +687,19 @@ copy_replication_slot(FunctionCallInfo fcinfo, bool logical_slot) /* Create new slot and acquire it */ if (logical_slot) + { + /* + * WAL required for building snapshot could be removed as we haven't + * reserved WAL yet. So we create a new logical replication slot + * without building an initial snapshot. A reasonable start point for + * decoding will be provided by the source slot. + */ create_logical_replication_slot(NameStr(*dst_name), plugin, temporary, - src_restart_lsn); + src_restart_lsn, + false); + } else create_physical_replication_slot(NameStr(*dst_name), true, @@ -703,6 +716,7 @@ copy_replication_slot(FunctionCallInfo fcinfo, bool logical_slot) TransactionId copy_xmin; TransactionId copy_catalog_xmin; XLogRecPtr copy_restart_lsn; + XLogRecPtr copy_confirmed_flush; bool copy_islogical; char *copy_name; @@ -714,6 +728,7 @@ copy_replication_slot(FunctionCallInfo fcinfo, bool logical_slot) copy_xmin = src->data.xmin; copy_catalog_xmin = src->data.catalog_xmin; copy_restart_lsn = src->data.restart_lsn; + copy_confirmed_flush = src->data.confirmed_flush; /* for existence check */ copy_name = pstrdup(NameStr(src->data.name)); @@ -738,6 +753,13 @@ copy_replication_slot(FunctionCallInfo fcinfo, bool logical_slot) NameStr(*src_name)), errdetail("The source replication slot was modified incompatibly during the copy operation."))); + /* The source slot must have a consistent snapshot */ + if (src_islogical && XLogRecPtrIsInvalid(copy_confirmed_flush)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot copy a logical replication slot that doesn't have confirmed_flush_lsn"), + errhint("Retry when the source replication slot creation is finished."))); + /* Install copied values again */ SpinLockAcquire(&MyReplicationSlot->mutex); MyReplicationSlot->effective_xmin = copy_effective_xmin; @@ -746,6 +768,7 @@ copy_replication_slot(FunctionCallInfo fcinfo, bool logical_slot) MyReplicationSlot->data.xmin = copy_xmin; MyReplicationSlot->data.catalog_xmin = copy_catalog_xmin; MyReplicationSlot->data.restart_lsn = copy_restart_lsn; + MyReplicationSlot->data.confirmed_flush = copy_confirmed_flush; SpinLockRelease(&MyReplicationSlot->mutex); ReplicationSlotMarkDirty(); --=-=-= Content-Type: text/plain -- cheers, arseny --=-=-=--