Обсуждение: pg_decode_message vs skip_empty_xacts and xact_wrote_changes

Поиск
Список
Период
Сортировка

pg_decode_message vs skip_empty_xacts and xact_wrote_changes

От
Ashutosh Bapat
Дата:
Hi All,
Every pg_decode routine except pg_decode_message  that decodes a
transactional change, has following block
/* output BEGIN if we haven't yet */
if (data->skip_empty_xacts && !txndata->xact_wrote_changes)
{
pg_output_begin(ctx, data, txn, false);
}
txndata->xact_wrote_changes = true;

But pg_decode_message() doesn't call pg_output_begin(). If a WAL
message is the first change in the transaction, it won't have a BEGIN
before it. That looks like a bug. Why is pg_decode_message()
exception?

-- 
Best Wishes,
Ashutosh Bapat



Re: pg_decode_message vs skip_empty_xacts and xact_wrote_changes

От
Amit Kapila
Дата:
On Mon, Jun 26, 2023 at 3:07 PM Ashutosh Bapat
<ashutosh.bapat.oss@gmail.com> wrote:
>
> Hi All,
> Every pg_decode routine except pg_decode_message  that decodes a
> transactional change, has following block
> /* output BEGIN if we haven't yet */
> if (data->skip_empty_xacts && !txndata->xact_wrote_changes)
> {
> pg_output_begin(ctx, data, txn, false);
> }
> txndata->xact_wrote_changes = true;
>
> But pg_decode_message() doesn't call pg_output_begin(). If a WAL
> message is the first change in the transaction, it won't have a BEGIN
> before it. That looks like a bug. Why is pg_decode_message()
> exception?
>

I can't see a reason why we shouldn't have a similar check for
transactional messages. So, agreed this is a bug.

--
With Regards,
Amit Kapila.



Re: pg_decode_message vs skip_empty_xacts and xact_wrote_changes

От
vignesh C
Дата:
On Mon, 26 Jun 2023 at 15:51, Amit Kapila <amit.kapila16@gmail.com> wrote:
>
> On Mon, Jun 26, 2023 at 3:07 PM Ashutosh Bapat
> <ashutosh.bapat.oss@gmail.com> wrote:
> >
> > Hi All,
> > Every pg_decode routine except pg_decode_message  that decodes a
> > transactional change, has following block
> > /* output BEGIN if we haven't yet */
> > if (data->skip_empty_xacts && !txndata->xact_wrote_changes)
> > {
> > pg_output_begin(ctx, data, txn, false);
> > }
> > txndata->xact_wrote_changes = true;
> >
> > But pg_decode_message() doesn't call pg_output_begin(). If a WAL
> > message is the first change in the transaction, it won't have a BEGIN
> > before it. That looks like a bug. Why is pg_decode_message()
> > exception?
> >
>
> I can't see a reason why we shouldn't have a similar check for
> transactional messages. So, agreed this is a bug.

Here is a patch having the fix for the same. I have not added any
tests as the existing tests cover this scenario. The same issue is
present in back branches too.
v1-0001-Call-pg_output_begin-in-pg_decode_message-if-it-i_master.patch
can be applied on master, PG15 and PG14,
v1-0001-Call-pg_output_begin-in-pg_decode_message-if-it-i_PG13.patch
patch can be applied on PG13, PG12 and PG11.
Thoughts?

Regards,
Vignesh

Вложения

Re: pg_decode_message vs skip_empty_xacts and xact_wrote_changes

От
Ashutosh Bapat
Дата:
Hi Vignesh,
Thanks for working on this.

On Wed, Jun 28, 2023 at 4:52 PM vignesh C <vignesh21@gmail.com> wrote:
>
> Here is a patch having the fix for the same. I have not added any
> tests as the existing tests cover this scenario. The same issue is
> present in back branches too.

Interesting, we have a test for this scenario and it accepts erroneous
output :).

> v1-0001-Call-pg_output_begin-in-pg_decode_message-if-it-i_master.patch
> can be applied on master, PG15 and PG14,
> v1-0001-Call-pg_output_begin-in-pg_decode_message-if-it-i_PG13.patch
> patch can be applied on PG13, PG12 and PG11.
> Thoughts?

I noticed this when looking at Tomas's patches for logical decoding of
sequences. The code block you have added is repeated in
pg_decode_change() and pg_decode_truncate(). It might be better to
push the conditions in pg_output_begin() itself so that any future
callsite of pg_output_begin() automatically takes care of these
conditions.

Otherwise the patches look good to me.

--
Best Wishes,
Ashutosh Bapat



Re: pg_decode_message vs skip_empty_xacts and xact_wrote_changes

От
vignesh C
Дата:
On Wed, 28 Jun 2023 at 19:26, Ashutosh Bapat
<ashutosh.bapat.oss@gmail.com> wrote:
>
> Hi Vignesh,
> Thanks for working on this.
>
> On Wed, Jun 28, 2023 at 4:52 PM vignesh C <vignesh21@gmail.com> wrote:
> >
> > Here is a patch having the fix for the same. I have not added any
> > tests as the existing tests cover this scenario. The same issue is
> > present in back branches too.
>
> Interesting, we have a test for this scenario and it accepts erroneous
> output :).
>
> > v1-0001-Call-pg_output_begin-in-pg_decode_message-if-it-i_master.patch
> > can be applied on master, PG15 and PG14,
> > v1-0001-Call-pg_output_begin-in-pg_decode_message-if-it-i_PG13.patch
> > patch can be applied on PG13, PG12 and PG11.
> > Thoughts?
>
> I noticed this when looking at Tomas's patches for logical decoding of
> sequences. The code block you have added is repeated in
> pg_decode_change() and pg_decode_truncate(). It might be better to
> push the conditions in pg_output_begin() itself so that any future
> callsite of pg_output_begin() automatically takes care of these
> conditions.

Thanks for the comments, here is an updated patch handling the above issue.

Regards,
Vignesh

Вложения

RE: pg_decode_message vs skip_empty_xacts and xact_wrote_changes

От
"Zhijie Hou (Fujitsu)"
Дата:
On Thursday, June 29, 2023 12:06 PM vignesh C <vignesh21@gmail.com> wrote:
> 
> On Wed, 28 Jun 2023 at 19:26, Ashutosh Bapat
> <ashutosh.bapat.oss@gmail.com> wrote:
> >
> > Hi Vignesh,
> > Thanks for working on this.
> >
> > On Wed, Jun 28, 2023 at 4:52 PM vignesh C <vignesh21@gmail.com> wrote:
> > >
> > > Here is a patch having the fix for the same. I have not added any
> > > tests as the existing tests cover this scenario. The same issue is
> > > present in back branches too.
> >
> > Interesting, we have a test for this scenario and it accepts erroneous
> > output :).
> >
> > > v1-0001-Call-pg_output_begin-in-pg_decode_message-if-it-i_master.pat
> > > ch can be applied on master, PG15 and PG14,
> > > v1-0001-Call-pg_output_begin-in-pg_decode_message-if-it-i_PG13.patch
> > > patch can be applied on PG13, PG12 and PG11.
> > > Thoughts?
> >
> > I noticed this when looking at Tomas's patches for logical decoding of
> > sequences. The code block you have added is repeated in
> > pg_decode_change() and pg_decode_truncate(). It might be better to
> > push the conditions in pg_output_begin() itself so that any future
> > callsite of pg_output_begin() automatically takes care of these
> > conditions.
> 
> Thanks for the comments, here is an updated patch handling the above issue.

Thanks for the patches.

I tried to understand the following check:

    /*
      * If asked to skip empty transactions, we'll emit BEGIN at the point
      * where the first operation is received for this transaction.
      */
-    if (data->skip_empty_xacts)
+    if (!(last_write ^ data->skip_empty_xacts) || txndata->xact_wrote_changes)
         return;

I might miss something, but would you mind elaborating on why we use "last_write" in this check?

Best Regard,
Hou zj

Re: pg_decode_message vs skip_empty_xacts and xact_wrote_changes

От
vignesh C
Дата:
On Thu, 29 Jun 2023 at 09:58, Zhijie Hou (Fujitsu)
<houzj.fnst@fujitsu.com> wrote:
>
> On Thursday, June 29, 2023 12:06 PM vignesh C <vignesh21@gmail.com> wrote:
> >
> > On Wed, 28 Jun 2023 at 19:26, Ashutosh Bapat
> > <ashutosh.bapat.oss@gmail.com> wrote:
> > >
> > > Hi Vignesh,
> > > Thanks for working on this.
> > >
> > > On Wed, Jun 28, 2023 at 4:52 PM vignesh C <vignesh21@gmail.com> wrote:
> > > >
> > > > Here is a patch having the fix for the same. I have not added any
> > > > tests as the existing tests cover this scenario. The same issue is
> > > > present in back branches too.
> > >
> > > Interesting, we have a test for this scenario and it accepts erroneous
> > > output :).
> > >
> > > > v1-0001-Call-pg_output_begin-in-pg_decode_message-if-it-i_master.pat
> > > > ch can be applied on master, PG15 and PG14,
> > > > v1-0001-Call-pg_output_begin-in-pg_decode_message-if-it-i_PG13.patch
> > > > patch can be applied on PG13, PG12 and PG11.
> > > > Thoughts?
> > >
> > > I noticed this when looking at Tomas's patches for logical decoding of
> > > sequences. The code block you have added is repeated in
> > > pg_decode_change() and pg_decode_truncate(). It might be better to
> > > push the conditions in pg_output_begin() itself so that any future
> > > callsite of pg_output_begin() automatically takes care of these
> > > conditions.
> >
> > Thanks for the comments, here is an updated patch handling the above issue.
>
> Thanks for the patches.
>
> I tried to understand the following check:
>
>         /*
>          * If asked to skip empty transactions, we'll emit BEGIN at the point
>          * where the first operation is received for this transaction.
>          */
> -       if (data->skip_empty_xacts)
> +       if (!(last_write ^ data->skip_empty_xacts) || txndata->xact_wrote_changes)
>                 return;
>
> I might miss something, but would you mind elaborating on why we use "last_write" in this check?

last_write is used to indicate if it is begin/"begin
prepare"(last_write is true) or change/truncate/message(last_write is
false).

We have specified logical XNOR which will be true for the following conditions:
Condition1: last_write && data->skip_empty_xacts  -> If it is
begin/begin prepare and user has specified skip empty transactions, we
will return from here, so that the begin message can be appended at
the point where the first operation is received for this transaction.
Condition2: !last_write && !data->skip_empty_xacts -> If it is
change/truncate or message and user has not specified skip empty
transactions, we will return from here as we would have appended the
begin earlier itself.
The txndata->xact_w6rote_changes will be set after the first operation
is received for this transaction during which we would have outputted
the begin message, this condition is to skip outputting begin message
if the begin message was already outputted.

Regards,
Vignesh



Re: pg_decode_message vs skip_empty_xacts and xact_wrote_changes

От
Amit Kapila
Дата:
On Wed, Jun 28, 2023 at 7:26 PM Ashutosh Bapat
<ashutosh.bapat.oss@gmail.com> wrote:
>
> Hi Vignesh,
> Thanks for working on this.
>
> On Wed, Jun 28, 2023 at 4:52 PM vignesh C <vignesh21@gmail.com> wrote:
> >
> > Here is a patch having the fix for the same. I have not added any
> > tests as the existing tests cover this scenario. The same issue is
> > present in back branches too.
>
> Interesting, we have a test for this scenario and it accepts erroneous
> output :).
>

This made me look at the original commit d6fa44fc which has introduced
this check and it seems this is done primarily to avoid spurious test
failures due to empty transactions. The proposed change won't help
with that. So, I am not sure if it is worth backpatching this change
as proposed. Though, I see the reasons to improve the code in HEAD due
to the following reasons (a) to maintain consistency among
transactional messages/changes (b) we will still emit Begin/Commit
with transactional messages when skip_empty_xacts is '0', see below
test:

SELECT 'init' FROM
pg_create_logical_replication_slot('regression_slot',
'test_decoding');
SELECT 'msg1' FROM pg_logical_emit_message(true, 'test', 'msg1');
SELECT 'msg2' FROM pg_logical_emit_message(false, 'test', 'msg2');

SELECT data FROM pg_logical_slot_peek_changes('regression_slot', NULL,
NULL, 'force-binary', '0', 'skip-empty-xacts', '1');
                            data
------------------------------------------------------------
 message: transactional: 1 prefix: test, sz: 4 content:msg1
 message: transactional: 0 prefix: test, sz: 4 content:msg2
(2 rows)

SELECT data FROM pg_logical_slot_peek_changes('regression_slot', NULL,
NULL, 'force-binary', '0', 'skip-empty-xacts', '0');
                            data
------------------------------------------------------------
 BEGIN 739
 message: transactional: 1 prefix: test, sz: 4 content:msg1
 COMMIT 739
 message: transactional: 0 prefix: test, sz: 4 content:msg2
(4 rows)

Thoughts?

--
With Regards,
Amit Kapila.



Re: pg_decode_message vs skip_empty_xacts and xact_wrote_changes

От
Amit Kapila
Дата:
On Thu, Jun 29, 2023 at 9:40 PM vignesh C <vignesh21@gmail.com> wrote:
>
> On Thu, 29 Jun 2023 at 09:58, Zhijie Hou (Fujitsu)
> <houzj.fnst@fujitsu.com> wrote:
> >
> > On Thursday, June 29, 2023 12:06 PM vignesh C <vignesh21@gmail.com> wrote:
> > >
> >
> > Thanks for the patches.
> >
> > I tried to understand the following check:
> >
> >         /*
> >          * If asked to skip empty transactions, we'll emit BEGIN at the point
> >          * where the first operation is received for this transaction.
> >          */
> > -       if (data->skip_empty_xacts)
> > +       if (!(last_write ^ data->skip_empty_xacts) || txndata->xact_wrote_changes)
> >                 return;
> >
> > I might miss something, but would you mind elaborating on why we use "last_write" in this check?
>
> last_write is used to indicate if it is begin/"begin
> prepare"(last_write is true) or change/truncate/message(last_write is
> false).
>
> We have specified logical XNOR which will be true for the following conditions:
> Condition1: last_write && data->skip_empty_xacts  -> If it is
> begin/begin prepare and user has specified skip empty transactions, we
> will return from here, so that the begin message can be appended at
> the point where the first operation is received for this transaction.
> Condition2: !last_write && !data->skip_empty_xacts -> If it is
> change/truncate or message and user has not specified skip empty
> transactions, we will return from here as we would have appended the
> begin earlier itself.
> The txndata->xact_w6rote_changes will be set after the first operation
> is received for this transaction during which we would have outputted
> the begin message, this condition is to skip outputting begin message
> if the begin message was already outputted.
>

I feel the use of last_write has reduced the readability of this part
of the code. It may be that we can add comments to make it clear but I
feel your previous version was much easier to understand.

--
With Regards,
Amit Kapila.



Re: pg_decode_message vs skip_empty_xacts and xact_wrote_changes

От
vignesh C
Дата:
On Fri, 30 Jun 2023 at 09:55, Amit Kapila <amit.kapila16@gmail.com> wrote:
>
> On Thu, Jun 29, 2023 at 9:40 PM vignesh C <vignesh21@gmail.com> wrote:
> >
> > On Thu, 29 Jun 2023 at 09:58, Zhijie Hou (Fujitsu)
> > <houzj.fnst@fujitsu.com> wrote:
> > >
> > > On Thursday, June 29, 2023 12:06 PM vignesh C <vignesh21@gmail.com> wrote:
> > > >
> > >
> > > Thanks for the patches.
> > >
> > > I tried to understand the following check:
> > >
> > >         /*
> > >          * If asked to skip empty transactions, we'll emit BEGIN at the point
> > >          * where the first operation is received for this transaction.
> > >          */
> > > -       if (data->skip_empty_xacts)
> > > +       if (!(last_write ^ data->skip_empty_xacts) || txndata->xact_wrote_changes)
> > >                 return;
> > >
> > > I might miss something, but would you mind elaborating on why we use "last_write" in this check?
> >
> > last_write is used to indicate if it is begin/"begin
> > prepare"(last_write is true) or change/truncate/message(last_write is
> > false).
> >
> > We have specified logical XNOR which will be true for the following conditions:
> > Condition1: last_write && data->skip_empty_xacts  -> If it is
> > begin/begin prepare and user has specified skip empty transactions, we
> > will return from here, so that the begin message can be appended at
> > the point where the first operation is received for this transaction.
> > Condition2: !last_write && !data->skip_empty_xacts -> If it is
> > change/truncate or message and user has not specified skip empty
> > transactions, we will return from here as we would have appended the
> > begin earlier itself.
> > The txndata->xact_w6rote_changes will be set after the first operation
> > is received for this transaction during which we would have outputted
> > the begin message, this condition is to skip outputting begin message
> > if the begin message was already outputted.
> >
>
> I feel the use of last_write has reduced the readability of this part
> of the code. It may be that we can add comments to make it clear but I
> feel your previous version was much easier to understand.

+1 for the first version patch, I also felt the first version is
easily understandable.

Regards,
Vignesh



Re: pg_decode_message vs skip_empty_xacts and xact_wrote_changes

От
Amit Kapila
Дата:
On Mon, Jul 3, 2023 at 4:49 PM vignesh C <vignesh21@gmail.com> wrote:
>
> +1 for the first version patch, I also felt the first version is
> easily understandable.
>

Okay, please find the slightly updated version (changed a comment and
commit message). Unless there are more comments, I'll push this in a
day or two.

--
With Regards,
Amit Kapila.



Re: pg_decode_message vs skip_empty_xacts and xact_wrote_changes

От
Amit Kapila
Дата:
On Wed, Jul 5, 2023 at 2:28 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
>
> On Mon, Jul 3, 2023 at 4:49 PM vignesh C <vignesh21@gmail.com> wrote:
> >
> > +1 for the first version patch, I also felt the first version is
> > easily understandable.
> >
>
> Okay, please find the slightly updated version (changed a comment and
> commit message). Unless there are more comments, I'll push this in a
> day or two.
>

oops, forgot to attach the patch.

--
With Regards,
Amit Kapila.

Вложения

Re: pg_decode_message vs skip_empty_xacts and xact_wrote_changes

От
Ashutosh Bapat
Дата:
On Wed, Jul 5, 2023 at 2:29 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
>
> On Wed, Jul 5, 2023 at 2:28 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
> >
> > On Mon, Jul 3, 2023 at 4:49 PM vignesh C <vignesh21@gmail.com> wrote:
> > >
> > > +1 for the first version patch, I also felt the first version is
> > > easily understandable.
> > >
> >
> > Okay, please find the slightly updated version (changed a comment and
> > commit message). Unless there are more comments, I'll push this in a
> > day or two.
> >
>
> oops, forgot to attach the patch.

I still think that we need to do something so that a new call to
pg_output_begin() automatically takes care of the conditions under
which it should be called. Otherwise, we will introduce a similar
problem in some other place in future.

--
Best Wishes,
Ashutosh Bapat



Re: pg_decode_message vs skip_empty_xacts and xact_wrote_changes

От
Amit Kapila
Дата:
On Wed, Jul 5, 2023 at 7:20 PM Ashutosh Bapat
<ashutosh.bapat.oss@gmail.com> wrote:
>
> On Wed, Jul 5, 2023 at 2:29 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
> >
> > On Wed, Jul 5, 2023 at 2:28 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
> > >
> > > On Mon, Jul 3, 2023 at 4:49 PM vignesh C <vignesh21@gmail.com> wrote:
> > > >
> > > > +1 for the first version patch, I also felt the first version is
> > > > easily understandable.
> > > >
> > >
> > > Okay, please find the slightly updated version (changed a comment and
> > > commit message). Unless there are more comments, I'll push this in a
> > > day or two.
> > >
> >
> > oops, forgot to attach the patch.
>
> I still think that we need to do something so that a new call to
> pg_output_begin() automatically takes care of the conditions under
> which it should be called. Otherwise, we will introduce a similar
> problem in some other place in future.
>

AFAIU, this problem is because we forget to conditionally call
pg_output_begin() from pg_decode_message() which can happen with or
without moving conditions inside pg_output_begin(). Also, it shouldn't
be done at the expense of complexity. I find the check added by
Vignesh's v2 patch (+ if (!(last_write ^ data->skip_empty_xacts) ||
txndata->xact_wrote_changes)) a bit difficult to understand and more
error-prone. The others like Hou-San also couldn't understand unless
Vignesh gave an explanation. I also thought of avoiding that check.
Basically, IIUC, the check is added because the patch also removed
'data->skip_empty_xacts' check from
pg_decode_begin_txn()/pg_decode_begin_prepare_txn(). Now, if retain
those checks then it is probably okay but again the similar checks are
still split and that doesn't appear to be better than the v1 or v3
patch version. I am not against improving code in this area and
probably we can consider doing it as a separate patch if we have
better ideas instead of combining it with this patch.

--
With Regards,
Amit Kapila.



Re: pg_decode_message vs skip_empty_xacts and xact_wrote_changes

От
Amit Kapila
Дата:
On Thu, Jul 6, 2023 at 2:06 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
>
> On Wed, Jul 5, 2023 at 7:20 PM Ashutosh Bapat
> <ashutosh.bapat.oss@gmail.com> wrote:
> >
> > On Wed, Jul 5, 2023 at 2:29 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
> > >
> > > On Wed, Jul 5, 2023 at 2:28 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
> > > >
> > > > On Mon, Jul 3, 2023 at 4:49 PM vignesh C <vignesh21@gmail.com> wrote:
> > > > >
> > > > > +1 for the first version patch, I also felt the first version is
> > > > > easily understandable.
> > > > >
> > > >
> > > > Okay, please find the slightly updated version (changed a comment and
> > > > commit message). Unless there are more comments, I'll push this in a
> > > > day or two.
> > > >
> > >
> > > oops, forgot to attach the patch.
> >
> > I still think that we need to do something so that a new call to
> > pg_output_begin() automatically takes care of the conditions under
> > which it should be called. Otherwise, we will introduce a similar
> > problem in some other place in future.
> >
>
> AFAIU, this problem is because we forget to conditionally call
> pg_output_begin() from pg_decode_message() which can happen with or
> without moving conditions inside pg_output_begin(). Also, it shouldn't
> be done at the expense of complexity. I find the check added by
> Vignesh's v2 patch (+ if (!(last_write ^ data->skip_empty_xacts) ||
> txndata->xact_wrote_changes)) a bit difficult to understand and more
> error-prone. The others like Hou-San also couldn't understand unless
> Vignesh gave an explanation. I also thought of avoiding that check.
> Basically, IIUC, the check is added because the patch also removed
> 'data->skip_empty_xacts' check from
> pg_decode_begin_txn()/pg_decode_begin_prepare_txn(). Now, if retain
> those checks then it is probably okay but again the similar checks are
> still split and that doesn't appear to be better than the v1 or v3
> patch version. I am not against improving code in this area and
> probably we can consider doing it as a separate patch if we have
> better ideas instead of combining it with this patch.
>

I have pushed this work. But feel free to propose further
improvements, if you have any better ideas.

--
With Regards,
Amit Kapila.



Re: pg_decode_message vs skip_empty_xacts and xact_wrote_changes

От
Ashutosh Bapat
Дата:
On Tue, Jul 11, 2023 at 5:59 PM Amit Kapila <amit.kapila16@gmail.com> wrote:

> >
>
> I have pushed this work. But feel free to propose further
> improvements, if you have any better ideas.
>

Thanks. We have fixed the problem. So things are better than they
were. I have been busy with something else so couldn't reply.


--
Best Wishes,
Ashutosh Bapat