RE: [BUG]Invalidate relcache when setting REPLICA IDENTITY - Mailing list pgsql-hackers

From houzj.fnst@fujitsu.com
Subject RE: [BUG]Invalidate relcache when setting REPLICA IDENTITY
Date
Msg-id OS0PR01MB57164ECDE335B3EC36F8AF7594949@OS0PR01MB5716.jpnprd01.prod.outlook.com
Whole thread Raw
In response to Re: [BUG]Invalidate relcache when setting REPLICA IDENTITY  (Amit Kapila <amit.kapila16@gmail.com>)
Responses Re: [BUG]Invalidate relcache when setting REPLICA IDENTITY
List pgsql-hackers
On Wed, Nov 10, 2021 7:29 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
> On Wed, Nov 10, 2021 at 12:42 PM tanghy.fnst@fujitsu.com
> <tanghy.fnst@fujitsu.com> wrote:
> >
> > Hi
> >
> > I think I found a bug related to logical replication(REPLICA IDENTITY in
> specific).
> > If I change REPLICA IDENTITY after creating publication,  the
> DELETE/UPDATE operations won't be replicated as expected.
> >
> > For example:
> > -- publisher
> > CREATE TABLE tbl(a int, b int);
> > ALTER TABLE tbl ALTER COLUMN a SET NOT NULL; CREATE UNIQUE INDEX
> idx_a
> > ON tbl(a); ALTER TABLE tbl ALTER COLUMN b SET NOT NULL; CREATE UNIQUE
> > INDEX idx_b ON tbl(b); ALTER TABLE tbl REPLICA IDENTITY USING INDEX
> > idx_a; CREATE PUBLICATION pub FOR TABLE tbl; ALTER TABLE tbl REPLICA
> > IDENTITY USING INDEX idx_b; INSERT INTO tbl VALUES (1,1);
> >
> > -- subscriber
> > CREATE TABLE tbl(a int, b int);
> > ALTER TABLE tbl ALTER COLUMN b SET NOT NULL; CREATE UNIQUE INDEX
> idx_b
> > ON tbl(b); ALTER TABLE tbl REPLICA IDENTITY USING INDEX idx_b; CREATE
> > SUBSCRIPTION sub CONNECTION 'dbname=postgres port=5432'
> PUBLICATION
> > pub; SELECT * FROM tbl;
> >
> > -- publisher
> > postgres=# UPDATE tbl SET a=-a;
> > UPDATE 1
> > postgres=# SELECT * FROM tbl;
> > a  | b
> > ----+---
> >  -1 | 1
> > (1 row)
> >
> > -- subscriber
> > postgres=# SELECT * FROM tbl;
> >  a | b
> > ---+---
> >  1 | 1
> > (1 row)
> >
> > (a in subscriber should be -1)
> >
> 
> I don't understand the purpose of idx_b in the above test case, why is it
> required to reproduce the problem?
> @@ -15488,6 +15488,7 @@ 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);
> + CacheInvalidateRelcache(rel);
> 
> CatalogTupleUpdate internally calls heap_update which calls
> CacheInvalidateHeapTuple(), why is that not sufficient for invalidation?

I think it's because the bug happens only when changing REPLICA IDENTITY index
from one(idx_a) to another one(idx_b).

When first time specify the REPLICA IDENTITY index, the code works well because
it will invoke 'CatalogTupleUpdate(pg_class,...' Which will invalidate the
target table's relcache.

    if (pg_class_form->relreplident != ri_type)
    {
        pg_class_form->relreplident = ri_type;
        CatalogTupleUpdate(pg_class, &pg_class_tuple->t_self, pg_class_tuple);
    }

But when changing REPLICA IDENTITY index, the code only invoke
'CatalogTupleUpdate(pg_index,' which seems only invalidate the index's cache not the
target table.

        if (dirty)
        {
            CatalogTupleUpdate(pg_index, &pg_index_tuple->t_self, pg_index_tuple);
            InvokeObjectPostAlterHookArg(IndexRelationId, thisIndexOid, 0,
                                         InvalidOid, is_internal);
        }

Best regards,
Hou zj

pgsql-hackers by date:

Previous
From: Thomas Munro
Date:
Subject: Re: Weird failure in explain.out with OpenBSD
Next
From: Andres Freund
Date:
Subject: Re: remove spurious CREATE INDEX CONCURRENTLY wait