Skip to content

Commit 0980adf

Browse files
author
Amit Kapila
committed
Fix data inconsistency between publisher and subscriber.
We were not updating the partition map cache in the subscriber even when the corresponding remote rel is changed. Due to this data was getting incorrectly replicated for partition tables after the publisher has changed the table schema. Fix it by resetting the required entries in the partition map cache after receiving a new relation mapping from the publisher. Reported-by: Shi Yu Author: Shi Yu, Hou Zhijie Reviewed-by: Amit Langote, Amit Kapila Backpatch-through: 13, where it was introduced Discussion: https://postgr.es/m/OSZPR01MB6310F46CD425A967E4AEF736FDA49@OSZPR01MB6310.jpnprd01.prod.outlook.com
1 parent d457cb4 commit 0980adf

File tree

4 files changed

+54
-1
lines changed

4 files changed

+54
-1
lines changed

src/backend/replication/logical/relation.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,40 @@ logicalrep_partmap_invalidate_cb(Datum arg, Oid reloid)
486486
}
487487
}
488488

489+
/*
490+
* Reset the entries in the partition map that refer to remoterel.
491+
*
492+
* Called when new relation mapping is sent by the publisher to update our
493+
* expected view of incoming data from said publisher.
494+
*
495+
* Note that we don't update the remoterel information in the entry here,
496+
* we will update the information in logicalrep_partition_open to avoid
497+
* unnecessary work.
498+
*/
499+
void
500+
logicalrep_partmap_reset_relmap(LogicalRepRelation *remoterel)
501+
{
502+
HASH_SEQ_STATUS status;
503+
LogicalRepPartMapEntry *part_entry;
504+
LogicalRepRelMapEntry *entry;
505+
506+
if (LogicalRepPartMap == NULL)
507+
return;
508+
509+
hash_seq_init(&status, LogicalRepPartMap);
510+
while ((part_entry = (LogicalRepPartMapEntry *) hash_seq_search(&status)) != NULL)
511+
{
512+
entry = &part_entry->relmapentry;
513+
514+
if (entry->remoterel.remoteid != remoterel->remoteid)
515+
continue;
516+
517+
logicalrep_relmap_free_entry(entry);
518+
519+
memset(entry, 0, sizeof(LogicalRepRelMapEntry));
520+
}
521+
}
522+
489523
/*
490524
* Initialize the partition map cache.
491525
*/

src/backend/replication/logical/worker.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,9 @@ apply_handle_relation(StringInfo s)
11911191

11921192
rel = logicalrep_read_rel(s);
11931193
logicalrep_relmap_update(rel);
1194+
1195+
/* Also reset all entries in the partition map that refer to remoterel. */
1196+
logicalrep_partmap_reset_relmap(rel);
11941197
}
11951198

11961199
/*

src/include/replication/logicalrelation.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ typedef struct LogicalRepRelMapEntry
3838
} LogicalRepRelMapEntry;
3939

4040
extern void logicalrep_relmap_update(LogicalRepRelation *remoterel);
41+
extern void logicalrep_partmap_reset_relmap(LogicalRepRelation *remoterel);
4142

4243
extern LogicalRepRelMapEntry *logicalrep_rel_open(LogicalRepRelId remoteid,
4344
LOCKMODE lockmode);

src/test/subscription/t/013_partition.pl

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
use warnings;
77
use PostgresNode;
88
use TestLib;
9-
use Test::More tests => 69;
9+
use Test::More tests => 70;
1010

1111
# setup
1212

@@ -841,3 +841,18 @@ BEGIN
841841
$result = $node_subscriber2->safe_psql('postgres',
842842
"SELECT a, b, c FROM tab5 ORDER BY 1");
843843
is($result, qq(3|1|), 'updates of tab5 replicated correctly after altering table on subscriber');
844+
845+
# Test that replication into the partitioned target table continues to
846+
# work correctly when the published table is altered.
847+
$node_publisher->safe_psql(
848+
'postgres', q{
849+
ALTER TABLE tab5 DROP COLUMN b, ADD COLUMN c INT;
850+
ALTER TABLE tab5 ADD COLUMN b INT;});
851+
852+
$node_publisher->safe_psql('postgres', "UPDATE tab5 SET c = 1 WHERE a = 3");
853+
854+
$node_publisher->wait_for_catchup('sub2');
855+
856+
$result = $node_subscriber2->safe_psql('postgres',
857+
"SELECT a, b, c FROM tab5 ORDER BY 1");
858+
is($result, qq(3||1), 'updates of tab5 replicated correctly after altering table on publisher');

0 commit comments

Comments
 (0)