mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-05 13:39:21 +02:00
Invalidate relcache when changing REPLICA IDENTITY index.
When changing REPLICA IDENTITY INDEX to another one, the target table's relcache was not being invalidated. This leads to skipping update/delete operations during apply on the subscriber side as the columns required to search corresponding rows won't get logged. Author: Tang Haiying, Hou Zhijie Reviewed-by: Euler Taveira, Amit Kapila Backpatch-through: 10 Discussion: https://postgr.es/m/OS0PR01MB61133CA11630DAE45BC6AD95FB939@OS0PR01MB6113.jpnprd01.prod.outlook.com
This commit is contained in:
parent
b062ca508c
commit
40fb634b1a
@ -13398,6 +13398,12 @@ relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid,
|
||||
CatalogTupleUpdate(pg_index, &pg_index_tuple->t_self, pg_index_tuple);
|
||||
InvokeObjectPostAlterHookArg(IndexRelationId, thisIndexOid, 0,
|
||||
InvalidOid, is_internal);
|
||||
/*
|
||||
* Invalidate the relcache for the table, so that after we commit
|
||||
* all sessions will refresh the table's replica identity index
|
||||
* before attempting any UPDATE or DELETE on the table.
|
||||
*/
|
||||
CacheInvalidateRelcache(rel);
|
||||
}
|
||||
heap_freetuple(pg_index_tuple);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use strict;
|
||||
use warnings;
|
||||
use PostgresNode;
|
||||
use TestLib;
|
||||
use Test::More tests => 3;
|
||||
use Test::More tests => 5;
|
||||
|
||||
# Bug #15114
|
||||
|
||||
@ -98,3 +98,87 @@ is( $node_publisher->psql(
|
||||
);
|
||||
|
||||
$node_publisher->stop('fast');
|
||||
|
||||
# https://postgr.es/m/OS0PR01MB61133CA11630DAE45BC6AD95FB939%40OS0PR01MB6113.jpnprd01.prod.outlook.com
|
||||
|
||||
# The bug was that when changing the REPLICA IDENTITY INDEX to another one, the
|
||||
# target table's relcache was not being invalidated. This leads to skipping
|
||||
# UPDATE/DELETE operations during apply on the subscriber side as the columns
|
||||
# required to search corresponding rows won't get logged.
|
||||
$node_publisher = get_new_node('publisher3');
|
||||
$node_publisher->init(allows_streaming => 'logical');
|
||||
$node_publisher->start;
|
||||
|
||||
$node_subscriber = get_new_node('subscriber3');
|
||||
$node_subscriber->init(allows_streaming => 'logical');
|
||||
$node_subscriber->start;
|
||||
|
||||
$node_publisher->safe_psql('postgres',
|
||||
"CREATE TABLE tab_replidentity_index(a int not null, b int not null)");
|
||||
$node_publisher->safe_psql('postgres',
|
||||
"CREATE UNIQUE INDEX idx_replidentity_index_a ON tab_replidentity_index(a)"
|
||||
);
|
||||
$node_publisher->safe_psql('postgres',
|
||||
"CREATE UNIQUE INDEX idx_replidentity_index_b ON tab_replidentity_index(b)"
|
||||
);
|
||||
|
||||
# use index idx_replidentity_index_a as REPLICA IDENTITY on publisher.
|
||||
$node_publisher->safe_psql('postgres',
|
||||
"ALTER TABLE tab_replidentity_index REPLICA IDENTITY USING INDEX idx_replidentity_index_a"
|
||||
);
|
||||
|
||||
$node_publisher->safe_psql('postgres',
|
||||
"INSERT INTO tab_replidentity_index VALUES(1, 1),(2, 2)");
|
||||
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
"CREATE TABLE tab_replidentity_index(a int not null, b int not null)");
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
"CREATE UNIQUE INDEX idx_replidentity_index_a ON tab_replidentity_index(a)"
|
||||
);
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
"CREATE UNIQUE INDEX idx_replidentity_index_b ON tab_replidentity_index(b)"
|
||||
);
|
||||
# use index idx_replidentity_index_b as REPLICA IDENTITY on subscriber because
|
||||
# it reflects the future scenario we are testing: changing REPLICA IDENTITY
|
||||
# INDEX.
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
"ALTER TABLE tab_replidentity_index REPLICA IDENTITY USING INDEX idx_replidentity_index_b"
|
||||
);
|
||||
|
||||
$publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
|
||||
$node_publisher->safe_psql('postgres',
|
||||
"CREATE PUBLICATION tap_pub FOR TABLE tab_replidentity_index");
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
"CREATE SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr application_name=tap_sub' PUBLICATION tap_pub"
|
||||
);
|
||||
|
||||
$node_publisher->wait_for_catchup('tap_sub');
|
||||
|
||||
# Also wait for initial table sync to finish
|
||||
my $synced_query =
|
||||
"SELECT count(1) = 0 FROM pg_subscription_rel WHERE srsubstate NOT IN ('s', 'r');";
|
||||
$node_subscriber->poll_query_until('postgres', $synced_query)
|
||||
or die "Timed out while waiting for subscriber to synchronize data";
|
||||
|
||||
is( $node_subscriber->safe_psql(
|
||||
'postgres', "SELECT * FROM tab_replidentity_index"),
|
||||
qq(1|1
|
||||
2|2),
|
||||
"check initial data on subscriber");
|
||||
|
||||
# Set REPLICA IDENTITY to idx_replidentity_index_b on publisher, then run UPDATE and DELETE.
|
||||
$node_publisher->safe_psql(
|
||||
'postgres', qq[
|
||||
ALTER TABLE tab_replidentity_index REPLICA IDENTITY USING INDEX idx_replidentity_index_b;
|
||||
UPDATE tab_replidentity_index SET a = -a WHERE a = 1;
|
||||
DELETE FROM tab_replidentity_index WHERE a = 2;
|
||||
]);
|
||||
|
||||
$node_publisher->wait_for_catchup('tap_sub');
|
||||
is( $node_subscriber->safe_psql(
|
||||
'postgres', "SELECT * FROM tab_replidentity_index"),
|
||||
qq(-1|1),
|
||||
"update works with REPLICA IDENTITY");
|
||||
|
||||
$node_publisher->stop('fast');
|
||||
$node_subscriber->stop('fast');
|
||||
|
Loading…
Reference in New Issue
Block a user