mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-12 18:34:36 +08: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
1b098da200
commit
354a1f8d22
@ -15488,6 +15488,12 @@ relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid,
|
|||||||
CatalogTupleUpdate(pg_index, &pg_index_tuple->t_self, pg_index_tuple);
|
CatalogTupleUpdate(pg_index, &pg_index_tuple->t_self, pg_index_tuple);
|
||||||
InvokeObjectPostAlterHookArg(IndexRelationId, thisIndexOid, 0,
|
InvokeObjectPostAlterHookArg(IndexRelationId, thisIndexOid, 0,
|
||||||
InvalidOid, is_internal);
|
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);
|
heap_freetuple(pg_index_tuple);
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ use strict;
|
|||||||
use warnings;
|
use warnings;
|
||||||
use PostgreSQL::Test::Cluster;
|
use PostgreSQL::Test::Cluster;
|
||||||
use PostgreSQL::Test::Utils;
|
use PostgreSQL::Test::Utils;
|
||||||
use Test::More tests => 5;
|
use Test::More tests => 7;
|
||||||
|
|
||||||
# Bug #15114
|
# Bug #15114
|
||||||
|
|
||||||
@ -224,3 +224,85 @@ $node_sub->safe_psql('postgres', "DROP TABLE tab1");
|
|||||||
$node_pub->stop('fast');
|
$node_pub->stop('fast');
|
||||||
$node_pub_sub->stop('fast');
|
$node_pub_sub->stop('fast');
|
||||||
$node_sub->stop('fast');
|
$node_sub->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 = PostgreSQL::Test::Cluster->new('publisher3');
|
||||||
|
$node_publisher->init(allows_streaming => 'logical');
|
||||||
|
$node_publisher->start;
|
||||||
|
|
||||||
|
$node_subscriber = PostgreSQL::Test::Cluster->new('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' PUBLICATION tap_pub"
|
||||||
|
);
|
||||||
|
|
||||||
|
$node_publisher->wait_for_catchup('tap_sub');
|
||||||
|
|
||||||
|
# Also wait for initial table sync to finish
|
||||||
|
$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