Re: long-standing data loss bug in initial sync of logical replication
Nitin Motiani <nitinmotiani@google.com>
From: Nitin Motiani <nitinmotiani@google.com>
To: Amit Kapila <amit.kapila16@gmail.com>
Cc: vignesh C <vignesh21@gmail.com>, Shlok Kyal <shlok.kyal.oss@gmail.com>, Masahiko Sawada <sawada.mshk@gmail.com>,
Tomas Vondra <tomas.vondra@enterprisedb.com>, Andres Freund <andres@anarazel.de>, PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
Date: 2024-09-02T15:49:41Z
Lists: pgsql-hackers
Commits
Same data as JSON:
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Fix typo in test file name added in commit 4909b38af0.
- 50b8ad30f754 18.0 landed
- d96206f259d6 17.5 landed
- 9987c94662c2 16.9 landed
- 90bc4523fd47 15.13 landed
- bb1bc9fa962e 14.18 landed
- 4164d6976316 13.21 landed
-
Fix data loss in logical replication.
- 247ee94150b6 13.21 landed
- 4909b38af034 18.0 landed
- cadaf0ac4637 17.5 landed
- 9a2f8b4f01d5 16.9 landed
- 9f21be08e884 15.13 landed
- 0434033e8bb5 14.18 landed
-
Avoid invalidating all RelationSyncCache entries on publication rename.
- 3abe9dc18892 18.0 cited
-
Remove obsolete RECHECK keyword completely
- 7da1bdc2c2f1 18.0 cited
-
Backport BackgroundPsql perl test module
- 187b8991f70f 16.4 cited
On Tue, Aug 20, 2024 at 4:10 PM Amit Kapila <amit.kapila16@gmail.com> wrote: > > On Thu, Aug 15, 2024 at 9:31 PM vignesh C <vignesh21@gmail.com> wrote: > > Since we are applying invalidations to all in-progress transactions, > > the publisher will only replicate half of the transaction data up to > > the point of invalidation, while the remaining half will not be > > replicated. > > Ex: > > Session1: > > BEGIN; > > INSERT INTO tab_conc VALUES (1); > > > > Session2: > > ALTER PUBLICATION regress_pub1 DROP TABLE tab_conc; > > > > Session1: > > INSERT INTO tab_conc VALUES (2); > > INSERT INTO tab_conc VALUES (3); > > COMMIT; > > > > After the above the subscriber data looks like: > > postgres=# select * from tab_conc ; > > a > > --- > > 1 > > (1 row) > > > > You can reproduce the issue using the attached test. > > I'm not sure if this behavior is ok. At present, we’ve replicated the > > first record within the same transaction, but the second and third > > records are being skipped. > > > > This can happen even without a concurrent DDL if some of the tables in > the database are part of the publication and others are not. In such a > case inserts for publicized tables will be replicated but other > inserts won't. Sending the partial data of the transaction isn't a > problem to me. Do you have any other concerns that I am missing? > Hi, I think that the partial data replication for one table is a bigger issue than the case of data being sent for a subset of the tables in the transaction. This can lead to inconsistent data if the same row is updated multiple times or deleted in the same transaction. In such a case if only the partial updates from the transaction are sent to the subscriber, it might end up with the data which was never visible on the publisher side. Here is an example I tried with the patch v8-001 : I created following 2 tables on the publisher and the subscriber : CREATE TABLE delete_test(id int primary key, name varchar(100)); CREATE TABLE update_test(id int primary key, name varchar(100)); I added both the tables to the publication p on the publisher and created a subscription s on the subscriber. I run 2 sessions on the publisher and do the following : Session 1 : BEGIN; INSERT INTO delete_test VALUES(0, 'Nitin'); Session 2 : ALTER PUBLICATION p DROP TABLE delete_test; Session 1 : DELETE FROM delete_test WHERE id=0; COMMIT; After the commit there should be no new row created on the publisher. But because the partial data was replicated, this is what the select on the subscriber shows : SELECT * FROM delete_test; id | name ----+----------- 0 | Nitin (1 row) I don't think the above is a common use case. But this is still an issue because the subscriber has the data which never existed on the publisher. Similar issue can be seen with an update command. Session 1 : BEGIN; INSERT INTO update_test VALUES(1, 'Chiranjiv'); Session 2 : ALTER PUBLICATION p DROP TABLE update_test; Session 1: UPDATE update_test SET name='Eeshan' where id=1; COMMIT; After the commit, this is the state on the publisher : SELECT * FROM update_test; 1 | Eeshan (1 row) While this is the state on the subscriber : SELECT * FROM update_test; 1 | Chiranjiv (1 row) I think the update during a transaction scenario might be more common than deletion right after insertion. But both of these seem like real issues to consider. Please let me know if I'm missing something. Thanks & Regards Nitin Motiani Google